diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2bfcca..ad2475e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,13 +5,6 @@ SPDX-License-Identifier: CC0-1.0
# Cert-D-Java Changelog
-## 0.2.2
-- Bump Bouncy Castle to `1.75`
-- Bump `sqlite-jdbc` to `3.42.0.0`
-
-## 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/build.gradle b/pgp-cert-d-java/build.gradle
index 19f1329..d59867d 100644
--- a/pgp-cert-d-java/build.gradle
+++ b/pgp-cert-d-java/build.gradle
@@ -32,7 +32,7 @@ dependencies {
testImplementation project(":pgp-cert-d-java-jdbc-sqlite-lookup")
testImplementation "org.bouncycastle:bcprov-jdk15to18:$bouncycastleVersion"
- testImplementation "org.bouncycastle:bcpg-jdk15to18:$bouncyPgVersion"
+ testImplementation "org.bouncycastle:bcpg-jdk15to18:$bouncycastleVersion"
}
animalsniffer {
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 1b27ffb..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,26 +66,25 @@ 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
+ * @return certificate or null
*
* @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/BaseDirectoryProviderTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/BaseDirectoryProviderTest.java
index f6af1be..357ba3f 100644
--- a/pgp-cert-d-java/src/test/java/pgp/cert_d/BaseDirectoryProviderTest.java
+++ b/pgp-cert-d-java/src/test/java/pgp/cert_d/BaseDirectoryProviderTest.java
@@ -18,7 +18,7 @@ public class BaseDirectoryProviderTest {
public void testGetDefaultBaseDir_Linux() {
assumeTrue(System.getProperty("os.name").equalsIgnoreCase("linux"));
File baseDir = BaseDirectoryProvider.getDefaultBaseDirForOS("linux");
- assertTrue(baseDir.getAbsolutePath().endsWith("pgp.cert.d"));
+ assertTrue(baseDir.getAbsolutePath().endsWith("/.local/share/pgp.cert.d"));
}
@Test
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 2903026..8e3b938 100644
--- a/version.gradle
+++ b/version.gradle
@@ -4,16 +4,15 @@
allprojects {
ext {
- shortVersion = '0.2.3'
- isSnapshot = true
+ shortVersion = '0.2.0'
+ isSnapshot = false
minAndroidSdk = 26
animalsnifferSignatureVersion = "$minAndroidSdk:8.0.0_r2"
javaSourceCompatibility = 1.8
- bouncycastleVersion = '1.75'
- bouncyPgVersion = "$bouncycastleVersion"
+ bouncycastleVersion = '1.71'
slf4jVersion = '1.7.36'
logbackVersion = '1.2.11'
junitVersion = '5.8.2'
- sqliteJdbcVersion = '3.42.0.0'
+ sqliteJdbcVersion = '3.36.0.3'
}
}