From 942b287bebaf8ab7b18e561871d711bf9ff6c90e Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 8 Aug 2022 13:50:59 +0200 Subject: [PATCH] Make Key and Certificate extend KeyMaterial, get rid of CertificateReader --- .../main/java/pgp/cert_d/BackendProvider.java | 3 -- .../SharedPGPCertificateDirectoryImpl.java | 49 ++++++++++++------- .../pgp/certificate_store/Certificate.java | 9 +--- .../CertificateReaderBackend.java | 29 ----------- .../main/java/pgp/certificate_store/Key.java | 2 +- .../pgp/certificate_store/KeyMaterial.java | 17 +++++++ .../certificate_store/KeyReaderBackend.java | 8 +-- 7 files changed, 55 insertions(+), 62 deletions(-) delete mode 100644 pgp-certificate-store/src/main/java/pgp/certificate_store/CertificateReaderBackend.java create mode 100644 pgp-certificate-store/src/main/java/pgp/certificate_store/KeyMaterial.java 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 66df316..ff93dd2 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,14 +4,11 @@ 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/SharedPGPCertificateDirectoryImpl.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/SharedPGPCertificateDirectoryImpl.java index 3e8ebe9..b44bdcf 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,54 +17,47 @@ 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.provideCertificateReaderBackend(), backendProvider.provideKeyReaderBackend()); + this(backendProvider.provideKeyReaderBackend()); } - public SharedPGPCertificateDirectoryImpl(CertificateReaderBackend certificateReaderBackend, - KeyReaderBackend keyReaderBackend) + public SharedPGPCertificateDirectoryImpl(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; @@ -96,8 +89,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(); @@ -106,6 +99,28 @@ 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 { @@ -116,7 +131,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi FileInputStream fileIn = new FileInputStream(certFile); BufferedInputStream bufferedIn = new BufferedInputStream(fileIn); - Certificate certificate = certificateReaderBackend.readCertificate(bufferedIn); + Certificate certificate = readCertificate(bufferedIn); return certificate; } @@ -155,7 +170,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi } FileInputStream fileIn = new FileInputStream(keyFile); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileIn); - Key key = keyReaderBackend.readKey(bufferedInputStream); + Key key = readKey(bufferedInputStream); return key; } @@ -197,7 +212,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi private Certificate _insert(InputStream data, CertificateMerger merge) throws IOException, BadDataException { - Certificate newCertificate = certificateReaderBackend.readCertificate(data); + Certificate newCertificate = readCertificate(data); Certificate existingCertificate; File certFile; try { @@ -218,7 +233,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi private Key _insertTrustRoot(InputStream data, KeyMerger merge) throws IOException, BadDataException { - Key newKey = keyReaderBackend.readKey(data); + Key newKey = readKey(data); Key existingKey; File keyFile; try { @@ -297,7 +312,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi private Certificate _insertSpecial(String specialName, InputStream data, CertificateMerger merge) throws IOException, BadNameException, BadDataException { - Certificate newCertificate = certificateReaderBackend.readCertificate(data); + Certificate newCertificate = readCertificate(data); Certificate existingCertificate = getBySpecialName(specialName); File certFile = resolver.getCertFileBySpecialName(specialName); @@ -338,7 +353,7 @@ public class SharedPGPCertificateDirectoryImpl implements SharedPGPCertificateDi @Override Certificate get() throws BadDataException { try { - Certificate certificate = certificateReaderBackend.readCertificate(new FileInputStream(certFile)); + Certificate certificate = 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 530e51c..f6501e8 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,14 +11,7 @@ import java.util.Set; /** * OpenPGP certificate (public key). */ -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(); +public abstract class Certificate implements KeyMaterial { /** * 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 deleted file mode 100644 index b3060f5..0000000 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/CertificateReaderBackend.java +++ /dev/null @@ -1,29 +0,0 @@ -// 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 00cc5c6..6425468 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 { +public abstract class Key implements KeyMaterial { /** * 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 new file mode 100644 index 0000000..d940a25 --- /dev/null +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/KeyMaterial.java @@ -0,0 +1,17 @@ +// 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 f774150..d99d8e2 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 Key} from the given {@link InputStream}. + * Read a {@link KeyMaterial} (either {@link Key} or {@link Certificate}) from the given {@link InputStream}. * * @param data input stream containing the binary representation of the key. - * @return key object + * @return key or certificate object * * @throws IOException in case of an IO error - * @throws BadDataException in case that the data stream does not contain a valid OpenPGP key + * @throws BadDataException in case that the data stream does not contain a valid OpenPGP key/certificate */ - Key readKey(InputStream data) throws IOException, BadDataException; + KeyMaterial read(InputStream data) throws IOException, BadDataException; }