diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/BackendProvider.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/BackendProvider.java index ff93dd2..66df316 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/BackendProvider.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/BackendProvider.java @@ -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(); diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/InMemorySubkeyLookup.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/InMemorySubkeyLookup.java index ec67ee0..1cd7862 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/InMemorySubkeyLookup.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/InMemorySubkeyLookup.java @@ -30,7 +30,6 @@ public class InMemorySubkeyLookup implements SubkeyLookup { public void storeCertificateSubkeyIds(String certificate, List subkeyIds) { for (long subkeyId : subkeyIds) { Set certificates = subkeyMap.get(subkeyId); - // noinspection Java8MapApi if (certificates == null) { certificates = new HashSet<>(); subkeyMap.put(subkeyId, certificates); diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/SharedPGPCertificateDirectoryImpl.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/SharedPGPCertificateDirectoryImpl.java index b44bdcf..3e8ebe9 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/SharedPGPCertificateDirectoryImpl.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/SharedPGPCertificateDirectoryImpl.java @@ -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(); } diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/Certificate.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/Certificate.java index f6501e8..530e51c 100644 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/Certificate.java +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/Certificate.java @@ -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. diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/CertificateReaderBackend.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/CertificateReaderBackend.java new file mode 100644 index 0000000..b3060f5 --- /dev/null +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/CertificateReaderBackend.java @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// 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; + +} diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/Key.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/Key.java index 6425468..00cc5c6 100644 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/Key.java +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/Key.java @@ -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. diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyMaterial.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyMaterial.java deleted file mode 100644 index d940a25..0000000 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyMaterial.java +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Paul Schaub -// -// 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(); - -} diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyReaderBackend.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyReaderBackend.java index d99d8e2..f774150 100644 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyReaderBackend.java +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyReaderBackend.java @@ -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; }