Add back support for getXIfChanged(Y, tag)

This commit is contained in:
Paul Schaub 2022-08-24 13:04:28 +02:00
parent d050cb5516
commit 27f4598437
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
15 changed files with 423 additions and 101 deletions

View file

@ -32,6 +32,23 @@ public interface PGPCertificateStore {
Certificate getCertificate(String identifier)
throws IOException, BadNameException, BadDataException;
/**
* Return the certificate that matches the given identifier, but only if it has been changed.
* Whether it has been changed is determined by calculating the tag in the directory
* (e.g. by looking at the inode and last modification date) and comparing the result with the tag provided by
* the caller.
*
* @param identifier certificate identifier
* @param tag tag by the caller
* @return certificate if it has been changed, null otherwise
*
* @throws IOException in case of an IO-error
* @throws BadNameException if the identifier is invalid
* @throws BadDataException if the certificate file contains invalid data
*/
Certificate getCertificateIfChanged(String identifier, Long tag)
throws IOException, BadNameException, BadDataException;
/**
* Return an {@link Iterator} over all certificates in the store that contain a subkey with the given
* subkey id.
@ -42,7 +59,7 @@ public interface PGPCertificateStore {
* @throws BadDataException if any of the certificate files contains invalid data
*/
Iterator<Certificate> getCertificatesBySubkeyId(long subkeyId)
throws IOException, BadDataException;
throws IOException, BadDataException;
/**
* Insert a certificate into the store.

View file

@ -4,13 +4,67 @@
package pgp.certificate_store.certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
/**
* OpenPGP certificate (public key).
*/
public abstract class Certificate implements KeyMaterial {
public class Certificate implements KeyMaterial {
private final byte[] bytes;
private final String fingerprint;
private final List<Long> subkeyIds;
private final Long tag;
/**
* Certificate constructor.
*
* @param bytes encoding of the certificate
* @param fingerprint fingerprint (lowercase hex characters)
* @param subkeyIds list of subkey ids
* @param tag tag
*/
public Certificate(byte[] bytes, String fingerprint, List<Long> subkeyIds, Long tag) {
this.bytes = bytes;
this.fingerprint = fingerprint;
this.subkeyIds = subkeyIds;
this.tag = tag;
}
/**
* Copy constructor to assign a new tag to the {@link Certificate}.
*
* @param cert certificate
* @param tag tag
*/
public Certificate(Certificate cert, Long tag) {
this(cert.bytes, cert.fingerprint, cert.subkeyIds, tag);
}
@Override
public String getFingerprint() {
return fingerprint;
}
@Override
public Certificate asCertificate() {
return this;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(bytes);
}
@Override
public Long getTag() {
return tag;
}
@Override
public List<Long> getSubkeyIds() {
return subkeyIds;
}
}

View file

@ -4,21 +4,74 @@
package pgp.certificate_store.certificate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
/**
* OpenPGP key (secret key).
*/
public abstract class Key implements KeyMaterial {
public class Key implements KeyMaterial {
private final byte[] bytes;
private final Certificate certificate;
private final Long tag;
/**
* Key constructor.
*
* @param bytes encoding of the key
* @param certificate associated certificate
* @param tag tag
*/
public Key(byte[] bytes, Certificate certificate, Long tag) {
this.bytes = bytes;
this.certificate = certificate;
this.tag = tag;
}
/**
* Copy constructor to change the tag of both the {@link Key} and its {@link Certificate}.
*
* @param key key
* @param tag tag
*/
public Key(Key key, Long tag) {
this(key.bytes, new Certificate(key.certificate, tag), tag);
}
/**
* Return the certificate part of this OpenPGP key.
*
* @return OpenPGP certificate
*/
public abstract Certificate getCertificate();
public Certificate getCertificate() {
return new Certificate(certificate, getTag());
}
@Override
public String getFingerprint() {
return certificate.getFingerprint();
}
@Override
public Certificate asCertificate() {
return getCertificate();
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(bytes);
}
@Override
public Long getTag() {
return tag;
}
@Override
public List<Long> getSubkeyIds() {
return certificate.getSubkeyIds();
}
}

View file

@ -4,7 +4,6 @@
package pgp.certificate_store.certificate;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
@ -19,23 +18,34 @@ public interface KeyMaterial {
*/
String getFingerprint();
/**
* Return the {@link Certificate} belonging to this key material.
* If this is already a {@link Certificate}, return this.
* If this is a {@link Key}, extract the {@link Certificate} and return it.
*
* @return certificate
*/
Certificate asCertificate();
/**
* Return an {@link InputStream} of the binary representation of the secret key.
*
* @return input stream
* @throws IOException in case of an IO error
*/
InputStream getInputStream() throws IOException;
InputStream getInputStream();
String getTag() throws IOException;
/**
* Return the tag belonging to this key material.
* The tag can be used to keep an application cache in sync with what is in the directory.
*
* @return tag
*/
Long getTag();
/**
* Return a {@link Set} containing key-ids of subkeys.
*
* @return subkeys
* @throws IOException in case of an IO error
*/
List<Long> getSubkeyIds() throws IOException;
List<Long> getSubkeyIds();
}

View file

@ -20,5 +20,5 @@ public interface KeyMaterialReaderBackend {
* @throws IOException in case of an IO error
* @throws BadDataException in case that the data stream does not contain a valid OpenPGP key/certificate
*/
KeyMaterial read(InputStream data) throws IOException, BadDataException;
KeyMaterial read(InputStream data, Long tag) throws IOException, BadDataException;
}