diff --git a/CHANGELOG.md b/CHANGELOG.md index be93a9d..ad2475e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,6 @@ SPDX-License-Identifier: CC0-1.0 # Cert-D-Java Changelog -## 0.2.1 -- Throw `NoSuchElementException` when querying non-existent certificates - ## 0.2.0 - `pgp-certificate-store`: - Rework `Certificate`, `Key` to inherit from `KeyMaterial` diff --git a/README.md b/README.md index 4dde81f..fb3cb90 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ SPDX-License-Identifier: Apache-2.0 This repository contains a number of modules defining OpenPGP certificate storage for Java and Android applications. -The module [pgp-certificate-store](pgp-certificate-store) defines generalized +The module [pgp-certificate-store](pgp-certificate-store] defines generalized interfaces for OpenPGP Certificate storage. It can be used by applications and libraries such as [PGPainless](https://pgpainless.org/) for certificate management. diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java index 87d2512..1d54212 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java @@ -15,8 +15,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -48,17 +46,13 @@ public class PGPCertificateDirectory if (!openPgpV4FingerprintPattern.matcher(fingerprint).matches()) { throw new BadNameException(); } - Certificate certificate = backend.readByFingerprint(fingerprint); - if (certificate == null) { - throw new NoSuchElementException(); - } - return certificate; + return backend.readByFingerprint(fingerprint); } @Override public Certificate getByFingerprintIfChanged(String fingerprint, long tag) throws IOException, BadNameException, BadDataException { - if (!Objects.equals(tag, backend.getTagForFingerprint(fingerprint))) { + if (tag != backend.getTagForFingerprint(fingerprint)) { return getByFingerprint(fingerprint); } return null; @@ -72,13 +66,13 @@ public class PGPCertificateDirectory if (keyMaterial != null) { return keyMaterial.asCertificate(); } - throw new NoSuchElementException(); + return null; } @Override public Certificate getBySpecialNameIfChanged(String specialName, long tag) throws IOException, BadNameException, BadDataException { - if (!Objects.equals(tag, backend.getTagForSpecialName(specialName))) { + if (tag != backend.getTagForSpecialName(specialName)) { return getBySpecialName(specialName); } return null; @@ -127,11 +121,7 @@ public class PGPCertificateDirectory @Override public KeyMaterial getTrustRoot() throws IOException, BadDataException { try { - KeyMaterial keyMaterial = backend.readBySpecialName(SpecialNames.TRUST_ROOT); - if (keyMaterial == null) { - throw new NoSuchElementException(); - } - return keyMaterial; + return backend.readBySpecialName(SpecialNames.TRUST_ROOT); } catch (BadNameException e) { throw new AssertionError("'" + SpecialNames.TRUST_ROOT + "' is implementation MUST"); } diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/ReadOnlyPGPCertificateDirectory.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/ReadOnlyPGPCertificateDirectory.java index 72b048b..0b1416c 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/ReadOnlyPGPCertificateDirectory.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/ReadOnlyPGPCertificateDirectory.java @@ -10,7 +10,6 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.util.Iterator; -import java.util.NoSuchElementException; /** * Interface for a read-only OpenPGP certificate directory. @@ -20,12 +19,12 @@ public interface ReadOnlyPGPCertificateDirectory { /** * Get the trust-root certificate. This is a certificate which is stored under the special name *
trust-root
. + * If no such certificate is found,
null
is returned. * * @return trust-root certificate * * @throws IOException in case of an IO error * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getTrustRootCertificate() throws IOException, BadDataException; @@ -37,25 +36,24 @@ public interface ReadOnlyPGPCertificateDirectory { * Otherwise. the changed certificate is returned. * * @param tag tag - * @return changed certificate, or null if the certificate is unchanged. + * @return changed certificate, or null if the certificate is unchanged or not found. * * @throws IOException in case of an IO error * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getTrustRootCertificateIfChanged(long tag) throws IOException, BadDataException; /** * Get the certificate identified by the given fingerprint. + * If no such certificate is found, return
null
. * * @param fingerprint lower-case fingerprint of the certificate - * @return certificate + * @return certificate or null if no such certificate has been found * * @throws IOException in case of an IO error * @throws BadNameException if the fingerprint is malformed * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getByFingerprint(String fingerprint) throws IOException, BadNameException, BadDataException; @@ -68,18 +66,18 @@ public interface ReadOnlyPGPCertificateDirectory { * * @param fingerprint lower-case fingerprint of the certificate * @param tag tag - * @return certificate or null if the certificate has not been changed + * @return certificate or null if the certificate has not been changed or has not been found * * @throws IOException in case of an IO error * @throws BadNameException if the fingerprint is malformed * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getByFingerprintIfChanged(String fingerprint, long tag) throws IOException, BadNameException, BadDataException; /** * Get the certificate identified by the given special name. + * If no such certificate is found,
null
is returned. * * @param specialName special name * @return certificate or null @@ -87,7 +85,6 @@ public interface ReadOnlyPGPCertificateDirectory { * @throws IOException in case of an IO error * @throws BadNameException if the special name is not known * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getBySpecialName(String specialName) throws IOException, BadNameException, BadDataException; @@ -105,7 +102,6 @@ public interface ReadOnlyPGPCertificateDirectory { * @throws IOException in case of an IO error * @throws BadNameException if the special name is not known * @throws BadDataException if the certificate contains bad data - * @throws NoSuchElementException if no such certificate is found */ Certificate getBySpecialNameIfChanged(String specialName, long tag) throws IOException, BadNameException, BadDataException; diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java index 08ac356..89e52ba 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java @@ -33,7 +33,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; import java.util.regex.Pattern; /** @@ -349,7 +348,7 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec private Long getTag(File file) throws IOException { if (!file.exists()) { - throw new NoSuchElementException(); + throw new IllegalArgumentException("File MUST exist."); } Path path = file.toPath(); BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); diff --git a/pgp-cert-d-java/src/test/java/pgp/cert_d/FileBasedPGPCertificateDirectoryTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/FileBasedPGPCertificateDirectoryTest.java deleted file mode 100644 index 8701e33..0000000 --- a/pgp-cert-d-java/src/test/java/pgp/cert_d/FileBasedPGPCertificateDirectoryTest.java +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package pgp.cert_d; - -import org.bouncycastle.util.io.Streams; -import org.junit.jupiter.api.Test; -import pgp.cert_d.backend.FileBasedCertificateDirectoryBackend; -import pgp.cert_d.dummy.TestKeyMaterialMerger; -import pgp.cert_d.dummy.TestKeyMaterialReaderBackend; -import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup; -import pgp.cert_d.subkey_lookup.SubkeyLookup; -import pgp.certificate_store.certificate.Certificate; -import pgp.certificate_store.certificate.KeyMaterialMerger; -import pgp.certificate_store.certificate.KeyMaterialReaderBackend; -import pgp.certificate_store.exception.BadDataException; -import pgp.certificate_store.exception.BadNameException; -import pgp.certificate_store.exception.NotAStoreException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Files; - -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assumptions.assumeFalse; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -public class FileBasedPGPCertificateDirectoryTest { - - private static final KeyMaterialMerger merger = new TestKeyMaterialMerger(); - @Test - public void testFileBasedCertificateDirectoryTagChangesWhenFileChanges() - throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException { - File tempDir = Files.createTempDirectory("file-based-changes").toFile(); - tempDir.deleteOnExit(); - PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory( - new TestKeyMaterialReaderBackend(), - tempDir, - new InMemorySubkeyLookup()); - FileBasedCertificateDirectoryBackend.FilenameResolver resolver = - new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir); - - // Insert certificate - Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger); - Long tag = certificate.getTag(); - assertNotNull(tag); - assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag)); - - Long oldTag = tag; - - Thread.sleep(10); - // Change the file on disk directly, this invalidates the tag due to changed modification date - File certFile = resolver.getCertFileByFingerprint(certificate.getFingerprint()); - FileOutputStream fileOut = new FileOutputStream(certFile); - Streams.pipeAll(certificate.getInputStream(), fileOut); - fileOut.write("\n".getBytes()); - fileOut.close(); - - // Old invalidated tag indicates a change, so the modified certificate is returned - certificate = directory.getByFingerprintIfChanged(certificate.getFingerprint(), oldTag); - assertNotNull(certificate); - - // new tag is valid - tag = certificate.getTag(); - assertNotEquals(oldTag, tag); - assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag)); - } - - @Test - public void fileBasedStoreInWriteProtectedAreaThrows() { - File root = new File("/"); - assumeTrue(root.exists(), "This test only runs on unix-like systems"); - File baseDirectory = new File(root, "pgp.cert.d"); - assumeFalse(baseDirectory.mkdirs(), "This test assumes that we cannot create dirs in /"); - - KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend(); - SubkeyLookup lookup = new InMemorySubkeyLookup(); - assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory( - reader, baseDirectory, lookup)); - } - - @Test - public void fileBasedStoreOnFileThrows() - throws IOException { - File tempDir = Files.createTempDirectory("containsAFile").toFile(); - tempDir.deleteOnExit(); - File baseDir = new File(tempDir, "pgp.cert.d"); - baseDir.createNewFile(); // this is a file, not a dir - - KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend(); - SubkeyLookup lookup = new InMemorySubkeyLookup(); - assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory( - reader, baseDir, lookup)); - } - - @Test - public void testCertificateStoredUnderWrongFingerprintThrowsBadData() - throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException { - File tempDir = Files.createTempDirectory("wrong-fingerprint").toFile(); - tempDir.deleteOnExit(); - PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory( - new TestKeyMaterialReaderBackend(), - tempDir, - new InMemorySubkeyLookup()); - FileBasedCertificateDirectoryBackend.FilenameResolver resolver = - new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir); - - // Insert Rons certificate - directory.insert(TestKeys.getRonCert(), merger); - - // Copy Rons cert to Cedrics cert file - File ronCert = resolver.getCertFileByFingerprint(TestKeys.RON_FP); - FileInputStream inputStream = new FileInputStream(ronCert); - File cedricCert = resolver.getCertFileByFingerprint(TestKeys.CEDRIC_FP); - cedricCert.getParentFile().mkdirs(); - cedricCert.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(cedricCert); - Streams.pipeAll(inputStream, outputStream); - inputStream.close(); - outputStream.close(); - - // Reading cedrics cert will fail, as it has Rons fingerprint - assertThrows(BadDataException.class, () -> directory.getByFingerprint(TestKeys.CEDRIC_FP)); - } -} diff --git a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java index f6bd858..4ffb865 100644 --- a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java +++ b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java @@ -6,9 +6,11 @@ package pgp.cert_d; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.Named; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import pgp.cert_d.backend.FileBasedCertificateDirectoryBackend; import pgp.cert_d.dummy.TestKeyMaterialMerger; import pgp.cert_d.dummy.TestKeyMaterialReaderBackend; import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup; @@ -22,13 +24,13 @@ import pgp.certificate_store.exception.NotAStoreException; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -import java.util.NoSuchElementException; import java.util.Set; import java.util.stream.Stream; @@ -66,55 +68,6 @@ public class PGPCertificateDirectoryTest { Arguments.of(Named.of("FileBasedCertificateDirectory", fileBased))); } - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentCertByFingerprintThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getByFingerprint("0000000000000000000000000000000000000000")); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentCertByFingerprintIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getByFingerprintIfChanged("0000000000000000000000000000000000000000", 12)); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentCertBySpecialNameThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getBySpecialName(SpecialNames.TRUST_ROOT)); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentCertBySpecialNameIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getBySpecialNameIfChanged(SpecialNames.TRUST_ROOT, 12)); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentTrustRootThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getTrustRoot()); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentTrustRootIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getTrustRootCertificateIfChanged(12)); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void getNonExistentTrustRootCertificateThrowsNoSuchElementException(PGPCertificateDirectory directory) { - assertThrows(NoSuchElementException.class, () -> - directory.getTrustRootCertificate()); - } - @ParameterizedTest @MethodSource("provideTestSubjects") public void lockDirectoryAndTryInsertWillFail(PGPCertificateDirectory directory) @@ -177,7 +130,7 @@ public class PGPCertificateDirectoryTest { @MethodSource("provideTestSubjects") public void testInsertAndGetSingleCert(PGPCertificateDirectory directory) throws BadDataException, IOException, InterruptedException, BadNameException { - assertThrows(NoSuchElementException.class, () -> directory.getByFingerprint(CEDRIC_FP), "Empty directory MUST NOT contain certificate"); + assertNull(directory.getByFingerprint(CEDRIC_FP), "Empty directory MUST NOT contain certificate"); Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger); assertEquals(CEDRIC_FP, certificate.getFingerprint(), "Fingerprint of inserted cert MUST match"); @@ -195,7 +148,7 @@ public class PGPCertificateDirectoryTest { @MethodSource("provideTestSubjects") public void testInsertAndGetTrustRootAndCert(PGPCertificateDirectory directory) throws BadDataException, IOException, InterruptedException { - assertThrows(NoSuchElementException.class, () -> directory.getTrustRoot()); + assertNull(directory.getTrustRoot()); KeyMaterial trustRootMaterial = directory.insertTrustRoot( TestKeys.getHarryKey(), merger); @@ -235,7 +188,6 @@ public class PGPCertificateDirectoryTest { assertNotNull(directory.getTrustRootCertificateIfChanged(tag + 1)); Long oldTag = tag; - Thread.sleep(10); // "update" key trustRootMaterial = directory.insertTrustRoot( TestKeys.getHarryKey(), merger); @@ -270,42 +222,38 @@ public class PGPCertificateDirectoryTest { assertNotNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag + 1)); } - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void testOverwriteTrustRoot(PGPCertificateDirectory directory) - throws BadDataException, IOException, InterruptedException { - directory.insertTrustRoot(TestKeys.getHarryKey(), merger); - assertEquals(HARRY_FP, directory.getTrustRoot().getFingerprint()); - assertTrue(directory.getTrustRoot() instanceof Key); + @Test + public void testFileBasedCertificateDirectoryTagChangesWhenFileChanges() throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException { + File tempDir = Files.createTempDirectory("file-based-changes").toFile(); + tempDir.deleteOnExit(); + PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory( + new TestKeyMaterialReaderBackend(), + tempDir, + new InMemorySubkeyLookup()); + FileBasedCertificateDirectoryBackend.FilenameResolver resolver = + new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir); - directory.insertTrustRoot(TestKeys.getCedricCert(), merger); - assertEquals(CEDRIC_FP, directory.getTrustRoot().getFingerprint()); - assertTrue(directory.getTrustRoot() instanceof Certificate); + // Insert certificate + Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger); + Long tag = certificate.getTag(); + assertNotNull(tag); + assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag)); + + Long oldTag = tag; + + // Change the file on disk directly, this invalidates the tag due to changed modification date + File certFile = resolver.getCertFileByFingerprint(certificate.getFingerprint()); + FileOutputStream fileOut = new FileOutputStream(certFile); + Streams.pipeAll(certificate.getInputStream(), fileOut); + fileOut.close(); + + // Old invalidated tag indicates a change, so the modified certificate is returned + certificate = directory.getByFingerprintIfChanged(certificate.getFingerprint(), oldTag); + assertNotNull(certificate); + + // new tag is valid + tag = certificate.getTag(); + assertNotEquals(oldTag, tag); + assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag)); } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void testOverwriteSpecialName(PGPCertificateDirectory directory) - throws BadDataException, IOException, InterruptedException, BadNameException { - directory.insertWithSpecialName(SpecialNames.TRUST_ROOT, TestKeys.getRonCert(), merger); - KeyMaterial bySpecialName = directory.getBySpecialName(SpecialNames.TRUST_ROOT); - assertEquals(RON_FP, bySpecialName.getFingerprint()); - - directory.insertWithSpecialName(SpecialNames.TRUST_ROOT, TestKeys.getHarryKey(), merger); - assertEquals(HARRY_FP, directory.getBySpecialName(SpecialNames.TRUST_ROOT).getFingerprint()); - } - - @ParameterizedTest - @MethodSource("provideTestSubjects") - public void testOverwriteByFingerprint(PGPCertificateDirectory directory) - throws BadDataException, IOException, InterruptedException, BadNameException { - directory.insert(TestKeys.getRonCert(), merger); - Certificate extracted = directory.getByFingerprint(RON_FP); - assertEquals(RON_FP, extracted.getFingerprint()); - - directory.insert(TestKeys.getRonCert(), merger); - extracted = directory.getByFingerprint(RON_FP); - assertEquals(RON_FP, extracted.getFingerprint()); - } - } diff --git a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java index 79b5fed..56fdac6 100644 --- a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java +++ b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java @@ -17,7 +17,6 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -53,7 +52,7 @@ public class PGPCertificateStoreAdapterTest { @Test public void testInsertGetCertificate() throws BadDataException, IOException, InterruptedException, BadNameException { - assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(TestKeys.CEDRIC_FP)); + assertNull(adapter.getCertificate(TestKeys.CEDRIC_FP)); assertFalse(adapter.getCertificates().hasNext()); Certificate certificate = adapter.insertCertificate(TestKeys.getCedricCert(), merger); @@ -71,7 +70,7 @@ public class PGPCertificateStoreAdapterTest { @Test public void testInsertGetTrustRoot() throws BadDataException, BadNameException, IOException, InterruptedException { - assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(SpecialNames.TRUST_ROOT)); + assertNull(adapter.getCertificate(SpecialNames.TRUST_ROOT)); Certificate certificate = adapter.insertCertificateBySpecialName( SpecialNames.TRUST_ROOT, TestKeys.getHarryKey(), merger); diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/PGPCertificateStore.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/PGPCertificateStore.java index 251229f..d0915b0 100644 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/PGPCertificateStore.java +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/PGPCertificateStore.java @@ -12,7 +12,6 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; -import java.util.NoSuchElementException; /** * Interface for an OpenPGP certificate (public key) store. @@ -21,6 +20,7 @@ public interface PGPCertificateStore { /** * 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 @@ -28,7 +28,6 @@ public interface PGPCertificateStore { * @throws IOException in case of an IO-error * @throws BadNameException if the identifier is invalid * @throws BadDataException if the certificate file contains invalid data - * @throws NoSuchElementException if no such certificate is found */ Certificate getCertificate(String identifier) throws IOException, BadNameException, BadDataException; @@ -46,7 +45,6 @@ public interface PGPCertificateStore { * @throws IOException in case of an IO-error * @throws BadNameException if the identifier is invalid * @throws BadDataException if the certificate file contains invalid data - * @throws NoSuchElementException if no such certificate is found */ Certificate getCertificateIfChanged(String identifier, Long tag) throws IOException, BadNameException, BadDataException; diff --git a/version.gradle b/version.gradle index ce74cbd..db46d9a 100644 --- a/version.gradle +++ b/version.gradle @@ -4,7 +4,7 @@ allprojects { ext { - shortVersion = '0.2.2' + shortVersion = '0.2.1' isSnapshot = true minAndroidSdk = 26 animalsnifferSignatureVersion = "$minAndroidSdk:8.0.0_r2"