Compare commits

..

No commits in common. "60779b921e351b1621197d35c789fbf6b7c4c64b" and "2b5da18fc63b071b92c1ef3145d594c175195a38" have entirely different histories.

8 changed files with 62 additions and 56 deletions

View file

@ -4,11 +4,14 @@
package pgp.cert_d;
import pgp.certificate_store.CertificateReaderBackend;
import pgp.certificate_store.CertificateMerger;
import pgp.certificate_store.KeyReaderBackend;
public abstract class BackendProvider {
public abstract CertificateReaderBackend provideCertificateReaderBackend();
public abstract KeyReaderBackend provideKeyReaderBackend();
public abstract CertificateMerger provideDefaultMergeCallback();

View file

@ -30,7 +30,6 @@ public class InMemorySubkeyLookup implements SubkeyLookup {
public void storeCertificateSubkeyIds(String certificate, List<Long> subkeyIds) {
for (long subkeyId : subkeyIds) {
Set<String> certificates = subkeyMap.get(subkeyId);
// noinspection Java8MapApi
if (certificates == null) {
certificates = new HashSet<>();
subkeyMap.put(subkeyId, certificates);

View file

@ -17,47 +17,54 @@ import java.util.Iterator;
import java.util.List;
import pgp.certificate_store.Key;
import pgp.certificate_store.KeyMaterial;
import pgp.certificate_store.KeyMerger;
import pgp.certificate_store.KeyReaderBackend;
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.CertificateReaderBackend;
import pgp.certificate_store.CertificateMerger;
public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDirectory {
private final FilenameResolver resolver;
private final LockingMechanism writeLock;
private final CertificateReaderBackend certificateReaderBackend;
private final KeyReaderBackend keyReaderBackend;
public SharedPGPCertificateDirectoryImpl(BackendProvider backendProvider)
throws NotAStoreException {
this(backendProvider.provideKeyReaderBackend());
this(backendProvider.provideCertificateReaderBackend(), backendProvider.provideKeyReaderBackend());
}
public SharedPGPCertificateDirectoryImpl(KeyReaderBackend keyReaderBackend)
public SharedPGPCertificateDirectoryImpl(CertificateReaderBackend certificateReaderBackend,
KeyReaderBackend keyReaderBackend)
throws NotAStoreException {
this(
BaseDirectoryProvider.getDefaultBaseDir(),
certificateReaderBackend,
keyReaderBackend);
}
public SharedPGPCertificateDirectoryImpl(File baseDirectory,
CertificateReaderBackend certificateReaderBackend,
KeyReaderBackend keyReaderBackend)
throws NotAStoreException {
this(
certificateReaderBackend,
keyReaderBackend,
new FilenameResolver(baseDirectory),
FileLockingMechanism.defaultDirectoryFileLock(baseDirectory));
}
public SharedPGPCertificateDirectoryImpl(
CertificateReaderBackend certificateReaderBackend,
KeyReaderBackend keyReaderBackend,
FilenameResolver filenameResolver,
LockingMechanism writeLock)
throws NotAStoreException {
this.certificateReaderBackend = certificateReaderBackend;
this.keyReaderBackend = keyReaderBackend;
this.resolver = filenameResolver;
this.writeLock = writeLock;
@ -89,8 +96,8 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
FileInputStream fileIn = new FileInputStream(certFile);
BufferedInputStream bufferedIn = new BufferedInputStream(fileIn);
Certificate certificate = certificateReaderBackend.readCertificate(bufferedIn);
Certificate certificate = readCertificate(bufferedIn);
if (!certificate.getFingerprint().equals(fingerprint)) {
// TODO: Figure out more suitable exception
throw new BadDataException();
@ -99,28 +106,6 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
return certificate;
}
private Certificate readCertificate(InputStream inputStream) throws BadDataException, IOException {
KeyMaterial record = keyReaderBackend.read(inputStream);
Certificate certificate = null;
if (record instanceof Certificate) {
certificate = (Certificate) record;
} else if (record instanceof Key) {
Key key = (Key) record;
certificate = key.getCertificate();
} else {
throw new BadDataException();
}
return certificate;
}
private Key readKey(InputStream inputStream) throws BadDataException, IOException {
KeyMaterial record = keyReaderBackend.read(inputStream);
if (record instanceof Key) {
return (Key) record;
}
throw new BadDataException();
}
@Override
public Certificate getBySpecialName(String specialName)
throws IOException, BadNameException, BadDataException {
@ -131,7 +116,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
FileInputStream fileIn = new FileInputStream(certFile);
BufferedInputStream bufferedIn = new BufferedInputStream(fileIn);
Certificate certificate = readCertificate(bufferedIn);
Certificate certificate = certificateReaderBackend.readCertificate(bufferedIn);
return certificate;
}
@ -170,7 +155,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
}
FileInputStream fileIn = new FileInputStream(keyFile);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileIn);
Key key = readKey(bufferedInputStream);
Key key = keyReaderBackend.readKey(bufferedInputStream);
return key;
}
@ -212,7 +197,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
private Certificate _insert(InputStream data, CertificateMerger merge)
throws IOException, BadDataException {
Certificate newCertificate = readCertificate(data);
Certificate newCertificate = certificateReaderBackend.readCertificate(data);
Certificate existingCertificate;
File certFile;
try {
@ -233,7 +218,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
private Key _insertTrustRoot(InputStream data, KeyMerger merge)
throws IOException, BadDataException {
Key newKey = readKey(data);
Key newKey = keyReaderBackend.readKey(data);
Key existingKey;
File keyFile;
try {
@ -312,7 +297,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
private Certificate _insertSpecial(String specialName, InputStream data, CertificateMerger merge)
throws IOException, BadNameException, BadDataException {
Certificate newCertificate = readCertificate(data);
Certificate newCertificate = certificateReaderBackend.readCertificate(data);
Certificate existingCertificate = getBySpecialName(specialName);
File certFile = resolver.getCertFileBySpecialName(specialName);
@ -353,7 +338,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi
@Override
Certificate get() throws BadDataException {
try {
Certificate certificate = readCertificate(new FileInputStream(certFile));
Certificate certificate = certificateReaderBackend.readCertificate(new FileInputStream(certFile));
if (!(subdirectory.getName() + certFile.getName()).equals(certificate.getFingerprint())) {
throw new BadDataException();
}

View file

@ -11,7 +11,14 @@ import java.util.Set;
/**
* OpenPGP certificate (public key).
*/
public abstract class Certificate implements KeyMaterial {
public abstract class Certificate {
/**
* Return the fingerprint of the certificate as 40 lowercase hex characters.
* TODO: Allow OpenPGP V5 fingerprints
*
* @return fingerprint
*/
public abstract String getFingerprint();
/**
* Return an {@link InputStream} of the binary representation of the certificate.

View file

@ -0,0 +1,29 @@
// 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 java.io.IOException;
import java.io.InputStream;
/**
* Interface definition for a class that can read {@link Certificate Certificates} from binary
* {@link InputStream InputStreams}.
*/
public interface CertificateReaderBackend {
/**
* Read a {@link Certificate} from the given {@link InputStream}.
*
* @param inputStream input stream containing the binary representation of the certificate.
* @return certificate object
*
* @throws IOException in case of an IO error
* @throws BadDataException in case that the input stream does not contain OpenPGP certificate data
*/
Certificate readCertificate(InputStream inputStream) throws IOException, BadDataException;
}

View file

@ -10,7 +10,7 @@ import java.io.InputStream;
/**
* OpenPGP key (secret key).
*/
public abstract class Key implements KeyMaterial {
public abstract class Key {
/**
* Return the certificate part of this OpenPGP key.

View file

@ -1,17 +0,0 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.certificate_store;
public interface KeyMaterial {
/**
* Return the fingerprint of the certificate as 40 lowercase hex characters.
* TODO: Allow OpenPGP V5 fingerprints
*
* @return fingerprint
*/
String getFingerprint();
}

View file

@ -12,13 +12,13 @@ import java.io.InputStream;
public interface KeyReaderBackend {
/**
* Read a {@link KeyMaterial} (either {@link Key} or {@link Certificate}) from the given {@link InputStream}.
* Read a {@link Key} from the given {@link InputStream}.
*
* @param data input stream containing the binary representation of the key.
* @return key or certificate object
* @return key object
*
* @throws IOException in case of an IO error
* @throws BadDataException in case that the data stream does not contain a valid OpenPGP key/certificate
* @throws BadDataException in case that the data stream does not contain a valid OpenPGP key
*/
KeyMaterial read(InputStream data) throws IOException, BadDataException;
Key readKey(InputStream data) throws IOException, BadDataException;
}