Compare commits
6 Commits
eab31b8c12
...
190194f932
Author | SHA1 | Date |
---|---|---|
Paul Schaub | 190194f932 | |
Paul Schaub | 08837f4999 | |
Paul Schaub | b827739892 | |
Paul Schaub | ceaa1e0c80 | |
Paul Schaub | 24f4e2d771 | |
Paul Schaub | a248e0d717 |
|
@ -5,6 +5,9 @@ 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`
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -15,6 +15,8 @@ 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;
|
||||
|
||||
|
@ -46,13 +48,17 @@ public class PGPCertificateDirectory
|
|||
if (!openPgpV4FingerprintPattern.matcher(fingerprint).matches()) {
|
||||
throw new BadNameException();
|
||||
}
|
||||
return backend.readByFingerprint(fingerprint);
|
||||
Certificate certificate = backend.readByFingerprint(fingerprint);
|
||||
if (certificate == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return certificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getByFingerprintIfChanged(String fingerprint, long tag)
|
||||
throws IOException, BadNameException, BadDataException {
|
||||
if (tag != backend.getTagForFingerprint(fingerprint)) {
|
||||
if (!Objects.equals(tag, backend.getTagForFingerprint(fingerprint))) {
|
||||
return getByFingerprint(fingerprint);
|
||||
}
|
||||
return null;
|
||||
|
@ -66,13 +72,13 @@ public class PGPCertificateDirectory
|
|||
if (keyMaterial != null) {
|
||||
return keyMaterial.asCertificate();
|
||||
}
|
||||
return null;
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getBySpecialNameIfChanged(String specialName, long tag)
|
||||
throws IOException, BadNameException, BadDataException {
|
||||
if (tag != backend.getTagForSpecialName(specialName)) {
|
||||
if (!Objects.equals(tag, backend.getTagForSpecialName(specialName))) {
|
||||
return getBySpecialName(specialName);
|
||||
}
|
||||
return null;
|
||||
|
@ -121,7 +127,11 @@ public class PGPCertificateDirectory
|
|||
@Override
|
||||
public KeyMaterial getTrustRoot() throws IOException, BadDataException {
|
||||
try {
|
||||
return backend.readBySpecialName(SpecialNames.TRUST_ROOT);
|
||||
KeyMaterial keyMaterial = backend.readBySpecialName(SpecialNames.TRUST_ROOT);
|
||||
if (keyMaterial == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return keyMaterial;
|
||||
} catch (BadNameException e) {
|
||||
throw new AssertionError("'" + SpecialNames.TRUST_ROOT + "' is implementation MUST");
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ 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;
|
||||
|
||||
/**
|
||||
|
@ -348,7 +349,7 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
|
||||
private Long getTag(File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
throw new IllegalArgumentException("File MUST exist.");
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
Path path = file.toPath();
|
||||
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// 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));
|
||||
}
|
||||
}
|
|
@ -6,11 +6,9 @@ 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;
|
||||
|
@ -24,13 +22,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;
|
||||
|
||||
|
@ -68,6 +66,55 @@ 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)
|
||||
|
@ -130,7 +177,7 @@ public class PGPCertificateDirectoryTest {
|
|||
@MethodSource("provideTestSubjects")
|
||||
public void testInsertAndGetSingleCert(PGPCertificateDirectory directory)
|
||||
throws BadDataException, IOException, InterruptedException, BadNameException {
|
||||
assertNull(directory.getByFingerprint(CEDRIC_FP), "Empty directory MUST NOT contain certificate");
|
||||
assertThrows(NoSuchElementException.class, () -> 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");
|
||||
|
@ -148,7 +195,7 @@ public class PGPCertificateDirectoryTest {
|
|||
@MethodSource("provideTestSubjects")
|
||||
public void testInsertAndGetTrustRootAndCert(PGPCertificateDirectory directory)
|
||||
throws BadDataException, IOException, InterruptedException {
|
||||
assertNull(directory.getTrustRoot());
|
||||
assertThrows(NoSuchElementException.class, () -> directory.getTrustRoot());
|
||||
|
||||
KeyMaterial trustRootMaterial = directory.insertTrustRoot(
|
||||
TestKeys.getHarryKey(), merger);
|
||||
|
@ -188,6 +235,7 @@ public class PGPCertificateDirectoryTest {
|
|||
assertNotNull(directory.getTrustRootCertificateIfChanged(tag + 1));
|
||||
|
||||
Long oldTag = tag;
|
||||
Thread.sleep(10);
|
||||
// "update" key
|
||||
trustRootMaterial = directory.insertTrustRoot(
|
||||
TestKeys.getHarryKey(), merger);
|
||||
|
@ -222,38 +270,42 @@ public class PGPCertificateDirectoryTest {
|
|||
assertNotNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag + 1));
|
||||
}
|
||||
|
||||
@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);
|
||||
@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);
|
||||
|
||||
// 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));
|
||||
directory.insertTrustRoot(TestKeys.getCedricCert(), merger);
|
||||
assertEquals(CEDRIC_FP, directory.getTrustRoot().getFingerprint());
|
||||
assertTrue(directory.getTrustRoot() instanceof Certificate);
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ 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;
|
||||
|
@ -52,7 +53,7 @@ public class PGPCertificateStoreAdapterTest {
|
|||
@Test
|
||||
public void testInsertGetCertificate()
|
||||
throws BadDataException, IOException, InterruptedException, BadNameException {
|
||||
assertNull(adapter.getCertificate(TestKeys.CEDRIC_FP));
|
||||
assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(TestKeys.CEDRIC_FP));
|
||||
assertFalse(adapter.getCertificates().hasNext());
|
||||
|
||||
Certificate certificate = adapter.insertCertificate(TestKeys.getCedricCert(), merger);
|
||||
|
@ -70,7 +71,7 @@ public class PGPCertificateStoreAdapterTest {
|
|||
@Test
|
||||
public void testInsertGetTrustRoot()
|
||||
throws BadDataException, BadNameException, IOException, InterruptedException {
|
||||
assertNull(adapter.getCertificate(SpecialNames.TRUST_ROOT));
|
||||
assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(SpecialNames.TRUST_ROOT));
|
||||
|
||||
Certificate certificate = adapter.insertCertificateBySpecialName(
|
||||
SpecialNames.TRUST_ROOT, TestKeys.getHarryKey(), merger);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
allprojects {
|
||||
ext {
|
||||
shortVersion = '0.2.1'
|
||||
shortVersion = '0.2.2'
|
||||
isSnapshot = true
|
||||
minAndroidSdk = 26
|
||||
animalsnifferSignatureVersion = "$minAndroidSdk:8.0.0_r2"
|
||||
|
|
Loading…
Reference in New Issue