mirror of
https://codeberg.org/PGPainless/cert-d-java.git
synced 2025-09-10 11:49:39 +02:00
Add back support for getXIfChanged(Y, tag)
This commit is contained in:
parent
d050cb5516
commit
27f4598437
15 changed files with 423 additions and 101 deletions
|
@ -33,6 +33,16 @@ public class PGPCertificateDirectory
|
|||
return backend.readByFingerprint(fingerprint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getByFingerprintIfChanged(String fingerprint, long tag)
|
||||
throws IOException, BadNameException, BadDataException {
|
||||
if (tag != backend.getTagForFingerprint(fingerprint)) {
|
||||
return getByFingerprint(fingerprint);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Certificate getBySpecialName(String specialName)
|
||||
throws BadNameException, BadDataException, IOException {
|
||||
|
@ -43,6 +53,15 @@ public class PGPCertificateDirectory
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getBySpecialNameIfChanged(String specialName, long tag)
|
||||
throws IOException, BadNameException, BadDataException {
|
||||
if (tag != backend.getTagForSpecialName(specialName)) {
|
||||
return getBySpecialName(specialName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getTrustRootCertificate()
|
||||
throws IOException, BadDataException {
|
||||
|
@ -53,6 +72,15 @@ public class PGPCertificateDirectory
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getTrustRootCertificateIfChanged(long tag) throws IOException, BadDataException {
|
||||
try {
|
||||
return getBySpecialNameIfChanged(SpecialNames.TRUST_ROOT, tag);
|
||||
} catch (BadNameException e) {
|
||||
throw new AssertionError("'" + SpecialNames.TRUST_ROOT + "' is an implementation MUST");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Certificate> items() {
|
||||
return backend.readItems();
|
||||
|
@ -179,6 +207,10 @@ public class PGPCertificateDirectory
|
|||
|
||||
Certificate doInsertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge)
|
||||
throws IOException, BadDataException, BadNameException;
|
||||
|
||||
Long getTagForFingerprint(String fingerprint) throws BadNameException, IOException;
|
||||
|
||||
Long getTagForSpecialName(String specialName) throws BadNameException, IOException;
|
||||
}
|
||||
|
||||
public interface LockingMechanism {
|
||||
|
|
|
@ -37,6 +37,16 @@ public class PGPCertificateStoreAdapter implements PGPCertificateStore {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate getCertificateIfChanged(String identifier, Long tag)
|
||||
throws IOException, BadNameException, BadDataException {
|
||||
if (SpecialNames.lookupSpecialName(identifier) != null) {
|
||||
return directory.getBySpecialNameIfChanged(identifier, tag);
|
||||
} else {
|
||||
return directory.getByFingerprintIfChanged(identifier.toLowerCase(), tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Certificate> getCertificatesBySubkeyId(long subkeyId)
|
||||
throws IOException, BadDataException {
|
||||
|
|
|
@ -16,12 +16,21 @@ public interface ReadOnlyPGPCertificateDirectory {
|
|||
Certificate getTrustRootCertificate()
|
||||
throws IOException, BadDataException;
|
||||
|
||||
Certificate getTrustRootCertificateIfChanged(long tag)
|
||||
throws IOException, BadDataException;
|
||||
|
||||
Certificate getByFingerprint(String fingerprint)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
Certificate getByFingerprintIfChanged(String fingerprint, long tag)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
Certificate getBySpecialName(String specialName)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
Certificate getBySpecialNameIfChanged(String specialName, long tag)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
Iterator<Certificate> items();
|
||||
|
||||
Iterator<String> fingerprints();
|
||||
|
|
|
@ -7,6 +7,7 @@ package pgp.cert_d.backend;
|
|||
import pgp.cert_d.PGPCertificateDirectory;
|
||||
import pgp.cert_d.SpecialNames;
|
||||
import pgp.certificate_store.certificate.Certificate;
|
||||
import pgp.certificate_store.certificate.Key;
|
||||
import pgp.certificate_store.certificate.KeyMaterial;
|
||||
import pgp.certificate_store.certificate.KeyMaterialMerger;
|
||||
import pgp.certificate_store.certificate.KeyMaterialReaderBackend;
|
||||
|
@ -25,6 +26,9 @@ import java.io.InputStream;
|
|||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
@ -160,10 +164,12 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
return null;
|
||||
}
|
||||
|
||||
long tag = getTagForFingerprint(fingerprint);
|
||||
|
||||
FileInputStream fileIn = new FileInputStream(certFile);
|
||||
BufferedInputStream bufferedIn = new BufferedInputStream(fileIn);
|
||||
|
||||
Certificate certificate = reader.read(bufferedIn).asCertificate();
|
||||
Certificate certificate = reader.read(bufferedIn, tag).asCertificate();
|
||||
if (!certificate.getFingerprint().equals(fingerprint)) {
|
||||
// TODO: Figure out more suitable exception
|
||||
throw new BadDataException();
|
||||
|
@ -179,9 +185,11 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
return null;
|
||||
}
|
||||
|
||||
long tag = getTagForSpecialName(specialName);
|
||||
|
||||
FileInputStream fileIn = new FileInputStream(certFile);
|
||||
BufferedInputStream bufferedIn = new BufferedInputStream(fileIn);
|
||||
KeyMaterial keyMaterial = reader.read(bufferedIn);
|
||||
KeyMaterial keyMaterial = reader.read(bufferedIn, tag);
|
||||
|
||||
return keyMaterial;
|
||||
}
|
||||
|
@ -214,7 +222,8 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
@Override
|
||||
Certificate get() throws BadDataException {
|
||||
try {
|
||||
Certificate certificate = reader.read(new FileInputStream(certFile)).asCertificate();
|
||||
long tag = getTag(certFile);
|
||||
Certificate certificate = reader.read(new FileInputStream(certFile), tag).asCertificate();
|
||||
if (!(subdirectory.getName() + certFile.getName()).equals(certificate.getFingerprint())) {
|
||||
throw new BadDataException();
|
||||
}
|
||||
|
@ -246,7 +255,7 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
|
||||
@Override
|
||||
public KeyMaterial doInsertTrustRoot(InputStream data, KeyMaterialMerger merge) throws BadDataException, IOException {
|
||||
KeyMaterial newCertificate = reader.read(data);
|
||||
KeyMaterial newCertificate = reader.read(data, null);
|
||||
KeyMaterial existingCertificate;
|
||||
File certFile;
|
||||
try {
|
||||
|
@ -256,18 +265,22 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
throw new BadDataException();
|
||||
}
|
||||
|
||||
if (existingCertificate != null && !newCertificate.getTag().equals(existingCertificate.getTag())) {
|
||||
if (existingCertificate != null) {
|
||||
newCertificate = merge.merge(newCertificate, existingCertificate);
|
||||
}
|
||||
|
||||
writeToFile(newCertificate.getInputStream(), certFile);
|
||||
|
||||
long tag = writeToFile(newCertificate.getInputStream(), certFile);
|
||||
if (newCertificate instanceof Key) {
|
||||
newCertificate = new Key((Key) newCertificate, tag);
|
||||
} else {
|
||||
newCertificate = new Certificate((Certificate) newCertificate, tag);
|
||||
}
|
||||
return newCertificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate doInsert(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException {
|
||||
KeyMaterial newCertificate = reader.read(data);
|
||||
KeyMaterial newCertificate = reader.read(data, null);
|
||||
Certificate existingCertificate;
|
||||
File certFile;
|
||||
try {
|
||||
|
@ -277,18 +290,17 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
throw new BadDataException();
|
||||
}
|
||||
|
||||
if (existingCertificate != null && !newCertificate.getTag().equals(existingCertificate.getTag())) {
|
||||
if (existingCertificate != null) {
|
||||
newCertificate = merge.merge(newCertificate, existingCertificate);
|
||||
}
|
||||
|
||||
writeToFile(newCertificate.getInputStream(), certFile);
|
||||
|
||||
return newCertificate.asCertificate();
|
||||
long tag = writeToFile(newCertificate.getInputStream(), certFile);
|
||||
return new Certificate(newCertificate.asCertificate(), tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate doInsertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, BadNameException {
|
||||
KeyMaterial newCertificate = reader.read(data);
|
||||
KeyMaterial newCertificate = reader.read(data, null);
|
||||
KeyMaterial existingCertificate;
|
||||
File certFile;
|
||||
try {
|
||||
|
@ -298,16 +310,41 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
throw new BadDataException();
|
||||
}
|
||||
|
||||
if (existingCertificate != null && !newCertificate.getTag().equals(existingCertificate.getTag())) {
|
||||
if (existingCertificate != null) {
|
||||
newCertificate = merge.merge(newCertificate, existingCertificate);
|
||||
}
|
||||
|
||||
writeToFile(newCertificate.getInputStream(), certFile);
|
||||
|
||||
return newCertificate.asCertificate();
|
||||
long tag = writeToFile(newCertificate.getInputStream(), certFile);
|
||||
return new Certificate(newCertificate.asCertificate(), tag);
|
||||
}
|
||||
|
||||
private void writeToFile(InputStream inputStream, File certFile)
|
||||
@Override
|
||||
public Long getTagForFingerprint(String fingerprint) throws BadNameException, IOException {
|
||||
File file = resolver.getCertFileByFingerprint(fingerprint);
|
||||
return getTag(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTagForSpecialName(String specialName) throws BadNameException, IOException {
|
||||
File file = resolver.getCertFileBySpecialName(specialName);
|
||||
return getTag(file);
|
||||
}
|
||||
|
||||
private Long getTag(File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
throw new IllegalArgumentException("File MUST exist.");
|
||||
}
|
||||
Path path = file.toPath();
|
||||
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
|
||||
|
||||
// On UNIX file systems, for example, fileKey() will return the device ID and inode
|
||||
int fileId = attrs.fileKey().hashCode();
|
||||
long lastMod = attrs.lastModifiedTime().toMillis();
|
||||
|
||||
return lastMod + (11L * fileId);
|
||||
}
|
||||
|
||||
private long writeToFile(InputStream inputStream, File certFile)
|
||||
throws IOException {
|
||||
certFile.getParentFile().mkdirs();
|
||||
if (!certFile.exists() && !certFile.createNewFile()) {
|
||||
|
@ -324,6 +361,7 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec
|
|||
|
||||
inputStream.close();
|
||||
fileOut.close();
|
||||
return getTag(certFile);
|
||||
}
|
||||
|
||||
public static class FilenameResolver {
|
||||
|
|
|
@ -7,6 +7,7 @@ package pgp.cert_d.backend;
|
|||
import pgp.cert_d.PGPCertificateDirectory;
|
||||
import pgp.cert_d.SpecialNames;
|
||||
import pgp.certificate_store.certificate.Certificate;
|
||||
import pgp.certificate_store.certificate.Key;
|
||||
import pgp.certificate_store.certificate.KeyMaterial;
|
||||
import pgp.certificate_store.certificate.KeyMaterialMerger;
|
||||
import pgp.certificate_store.certificate.KeyMaterialReaderBackend;
|
||||
|
@ -91,7 +92,7 @@ public class InMemoryCertificateDirectoryBackend implements PGPCertificateDirect
|
|||
@Override
|
||||
public KeyMaterial doInsertTrustRoot(InputStream data, KeyMaterialMerger merge)
|
||||
throws BadDataException, IOException {
|
||||
KeyMaterial update = reader.read(data);
|
||||
KeyMaterial update = reader.read(data, null);
|
||||
KeyMaterial existing = null;
|
||||
try {
|
||||
existing = readBySpecialName(SpecialNames.TRUST_ROOT);
|
||||
|
@ -100,6 +101,11 @@ public class InMemoryCertificateDirectoryBackend implements PGPCertificateDirect
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
KeyMaterial merged = merge.merge(update, existing);
|
||||
if (merged instanceof Key) {
|
||||
merged = new Key((Key) merged, System.currentTimeMillis());
|
||||
} else {
|
||||
merged = new Certificate((Certificate) merged, System.currentTimeMillis());
|
||||
}
|
||||
keyMaterialSpecialNameMap.put(SpecialNames.TRUST_ROOT, merged);
|
||||
return merged;
|
||||
}
|
||||
|
@ -108,9 +114,10 @@ public class InMemoryCertificateDirectoryBackend implements PGPCertificateDirect
|
|||
@Override
|
||||
public Certificate doInsert(InputStream data, KeyMaterialMerger merge)
|
||||
throws IOException, BadDataException {
|
||||
KeyMaterial update = reader.read(data);
|
||||
KeyMaterial update = reader.read(data, null);
|
||||
Certificate existing = readByFingerprint(update.getFingerprint());
|
||||
Certificate merged = merge.merge(update, existing).asCertificate();
|
||||
merged = new Certificate(merged, System.currentTimeMillis());
|
||||
certificateFingerprintMap.put(update.getFingerprint(), merged);
|
||||
return merged;
|
||||
}
|
||||
|
@ -118,10 +125,36 @@ public class InMemoryCertificateDirectoryBackend implements PGPCertificateDirect
|
|||
@Override
|
||||
public Certificate doInsertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge)
|
||||
throws IOException, BadDataException, BadNameException {
|
||||
KeyMaterial keyMaterial = reader.read(data);
|
||||
KeyMaterial keyMaterial = reader.read(data, null);
|
||||
KeyMaterial existing = readBySpecialName(specialName);
|
||||
KeyMaterial merged = merge.merge(keyMaterial, existing);
|
||||
if (merged instanceof Key) {
|
||||
merged = new Key((Key) merged, System.currentTimeMillis());
|
||||
} else {
|
||||
merged = new Certificate((Certificate) merged, System.currentTimeMillis());
|
||||
}
|
||||
keyMaterialSpecialNameMap.put(specialName, merged);
|
||||
return merged.asCertificate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTagForFingerprint(String fingerprint) throws BadNameException, IOException {
|
||||
Certificate certificate = certificateFingerprintMap.get(fingerprint);
|
||||
if (certificate == null) {
|
||||
return null;
|
||||
}
|
||||
return certificate.getTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTagForSpecialName(String specialName) throws BadNameException, IOException {
|
||||
if (SpecialNames.lookupSpecialName(specialName) == null) {
|
||||
throw new BadNameException("Invalid special name " + specialName);
|
||||
}
|
||||
KeyMaterial tagged = keyMaterialSpecialNameMap.get(specialName);
|
||||
if (tagged == null) {
|
||||
return null;
|
||||
}
|
||||
return tagged.getTag();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue