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 668bd2f..3a3a9d7 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 @@ -17,12 +17,23 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +/** + * Implementation of the Shared PGP Certificate Directory. + * + * @see Shared PGP Certificate Directory Specification + */ public class PGPCertificateDirectory implements ReadOnlyPGPCertificateDirectory, WritingPGPCertificateDirectory, SubkeyLookup { final Backend backend; final SubkeyLookup subkeyLookup; + /** + * Constructor for a PGP certificate directory. + * + * @param backend storage backend + * @param subkeyLookup subkey lookup mechanism to map subkey-ids to certificates + */ public PGPCertificateDirectory(Backend backend, SubkeyLookup subkeyLookup) { this.backend = backend; this.subkeyLookup = subkeyLookup; @@ -189,30 +200,119 @@ public class PGPCertificateDirectory subkeyLookup.storeCertificateSubkeyIds(certificate, subkeyIds); } + /** + * Storage backend. + */ public interface Backend { + /** + * Get the locking mechanism to write-lock the backend. + * + * @return lock + */ LockingMechanism getLock(); + /** + * Read a {@link Certificate} by its OpenPGP fingerprint. + * + * @param fingerprint fingerprint + * @return certificate + * + * @throws BadNameException if the fingerprint is malformed + * @throws IOException in case of an IO error + * @throws BadDataException if the certificate contains bad data + */ Certificate readByFingerprint(String fingerprint) throws BadNameException, IOException, BadDataException; + /** + * Read a {@link Certificate} or {@link pgp.certificate_store.certificate.Key} by the given special name. + * + * @param specialName special name + * @return certificate or key + * + * @throws BadNameException if the special name is not known + * @throws IOException in case of an IO error + * @throws BadDataException if the certificate contains bad data + */ KeyMaterial readBySpecialName(String specialName) throws BadNameException, IOException, BadDataException; + /** + * Return an {@link Iterator} of all {@link Certificate Certificates} in the store, except for certificates + * stored under a special name. + * + * @return iterator + */ Iterator readItems(); + /** + * Insert a {@link pgp.certificate_store.certificate.Key} or {@link Certificate} as trust-root. + * + * @param data input stream containing the key material + * @param merge callback to merge the key material with existing key material + * @return merged or inserted key material + * + * @throws BadDataException if the data stream or existing key material contains bad data + * @throws IOException in case of an IO error + */ KeyMaterial doInsertTrustRoot(InputStream data, KeyMaterialMerger merge) throws BadDataException, IOException; + /** + * Insert a {@link Certificate} identified by its fingerprint into the directory. + * + * @param data input stream containing the certificate data + * @param merge callback to merge the certificate with existing key material + * @return merged or inserted certificate + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or existing certificate contains bad data + */ Certificate doInsert(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException; + /** + * Insert a {@link pgp.certificate_store.certificate.Key} or {@link Certificate} under the given special name. + * + * @param specialName special name to identify the key material with + * @param data data stream containing the key or certificate + * @param merge callback to merge the key/certificate with existing key material + * @return certificate component of the merged or inserted key material + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or existing key material contains bad data + * @throws BadNameException if the special name is not known + */ Certificate doInsertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, BadNameException; + /** + * Calculate the tag of the certificate with the given fingerprint. + * + * @param fingerprint fingerprint + * @return tag + * + * @throws BadNameException if the fingerprint is malformed + * @throws IOException in case of an IO error + * @throws IllegalArgumentException if the certificate does not exist + */ Long getTagForFingerprint(String fingerprint) throws BadNameException, IOException; + /** + * Calculate the tag of the certificate identified by the given special name. + * + * @param specialName special name + * @return tag + * + * @throws BadNameException if the special name is not known + * @throws IOException in case of an IO error + * @throws IllegalArgumentException if the certificate or key does not exist + */ Long getTagForSpecialName(String specialName) throws BadNameException, IOException; } + /** + * Interface for a write-locking mechanism. + */ public interface LockingMechanism { /** @@ -234,6 +334,11 @@ public class PGPCertificateDirectory */ boolean tryLockDirectory() throws IOException; + /** + * Return true if the lock is in locked state. + * + * @return true if locked + */ boolean isLocked(); /** 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 8c5efdc..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 @@ -11,27 +11,113 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.util.Iterator; +/** + * Interface for a read-only OpenPGP certificate directory. + */ 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 + */ Certificate getTrustRootCertificate() throws IOException, BadDataException; + /** + * Get the trust-root certificate if it has changed. + * This method uses the
tag
to calculate if the certificate might have changed. + * If the computed tag equals the given tag, the certificate has not changed, so
null
is returned. + * Otherwise. the changed certificate is returned. + * + * @param tag tag + * @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 + */ 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 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 + */ Certificate getByFingerprint(String fingerprint) throws IOException, BadNameException, BadDataException; + /** + * Get the certificate identified by the given fingerprint if it has changed. + * This method uses the
tag
to calculate, if the certificate might have changed. + * If the computed tag equals the given tag, the certificate has not changed, so
null
is returned. + * Otherwise, the changed certificate is returned. + * + * @param fingerprint lower-case fingerprint of the certificate + * @param tag tag + * @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 + */ 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 + * + * @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 + */ Certificate getBySpecialName(String specialName) throws IOException, BadNameException, BadDataException; + /** + * Get the certificate identified by the given special name or null, if it has not been changed. + * This method uses the
tag
to calculate, if the certificate might have changed. + * If the computed tag equals the given tag, the certificate has not changed, so
null
is returned. + * Otherwise, the changed certificate is returned. + * + * @param specialName special name + * @param tag tag + * @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 + */ Certificate getBySpecialNameIfChanged(String specialName, long tag) throws IOException, BadNameException, BadDataException; + /** + * Get all certificates in the directory, except for certificates which are stored by special name. + * + * @return iterator of certificates + */ Iterator items(); + /** + * Get the fingerprints of all certificates in the directory, except for certificates which are stored by + * special name. + * + * @return iterator of fingerprints + */ Iterator fingerprints(); } diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/WritingPGPCertificateDirectory.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/WritingPGPCertificateDirectory.java index 2857165..e5371fc 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/WritingPGPCertificateDirectory.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/WritingPGPCertificateDirectory.java @@ -13,26 +13,113 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.io.InputStream; +/** + * Interface for a writing OpenPGP certificate directory. + */ public interface WritingPGPCertificateDirectory { + /** + * Return the certificate or key identified by the special name
trust-root
. + * + * @return trust-root key or certificate + * + * @throws IOException in case of an IO error + * @throws BadDataException if the certificate contains bad data + */ KeyMaterial getTrustRoot() throws IOException, BadDataException; + /** + * Insert a key or certificate under the special name
trust-root
. + * This method blocks until the key material has been written. + * + * @param data input stream containing the key or certificate + * @param merge key material merger to merge the key or certificate with existing key material + * @return the merged or inserted key or certificate + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or the existing trust-root key material contains bad data + * @throws InterruptedException if the thread is interrupted + */ KeyMaterial insertTrustRoot(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, InterruptedException; + /** + * Insert a key or certificate under the special name
trust-root
. + * Contrary to {@link #insertTrustRoot(InputStream, KeyMaterialMerger)}, this method does not block. + * Instead, it returns null if the write-lock cannot be obtained. + * + * @param data input stream containing the key or certificate + * @param merge key material merger to merge the key or certificate with existing key material + * @return the merged or inserted key or certificate, or null if the write-lock cannot be obtained + * + * @throws IOException in case of an IO error + * @throws BadDataException if the thread is interrupted + */ KeyMaterial tryInsertTrustRoot(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException; + /** + * Insert a certificate identified by its fingerprint. + * This method blocks until the certificate has been written. + * + * @param data input stream containing the certificate data + * @param merge merge callback to merge the certificate with existing certificate material + * @return the merged or inserted certificate + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or existing certificate contains bad data + * @throws InterruptedException if the thread is interrupted + */ Certificate insert(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, InterruptedException; + /** + * Insert a certificate identified by its fingerprint. + * Contrary to {@link #insert(InputStream, KeyMaterialMerger)}, this method does not block. + * Instead, it returns null if the write-lock cannot be obtained. + * + * @param data input stream containing the certificate data + * @param merge merge callback to merge the certificate with existing certificate material + * @return the merged or inserted certificate + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or existing certificate contains bad data + */ Certificate tryInsert(InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException; + /** + * Insert a certificate or key under the given special name. + * This method blocks until the certificate/key has been written. + * + * @param specialName special name under which the key material shall be inserted + * @param data input stream containing the key/certificate data + * @param merge callback to merge the key/certificate with existing key material + * @return certificate component of the merged or inserted key material data + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or the existing certificate contains bad data + * @throws BadNameException if the special name is not known + * @throws InterruptedException if the thread is interrupted + */ Certificate insertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, BadNameException, InterruptedException; + /** + * Insert a certificate or key under the given special name. + * Contrary to {@link #insertWithSpecialName(String, InputStream, KeyMaterialMerger)}, this method does not block. + * Instead, it returns null if the write-lock cannot be obtained. + * + * @param specialName special name under which the key material shall be inserted + * @param data input stream containing the key material + * @param merge callback to merge the key/certificate with existing key material + * @return certificate component of the merged or inserted key material + * + * @throws IOException in case of an IO error + * @throws BadDataException if the data stream or existing key material contains bad data + * @throws BadNameException if the special name is not known + */ Certificate tryInsertWithSpecialName(String specialName, InputStream data, KeyMaterialMerger merge) throws IOException, BadDataException, BadNameException; diff --git a/pgp-certificate-store/src/main/java/pgp/certificate_store/certificate/KeyMaterialReaderBackend.java b/pgp-certificate-store/src/main/java/pgp/certificate_store/certificate/KeyMaterialReaderBackend.java index 42b3e2c..c921d64 100644 --- a/pgp-certificate-store/src/main/java/pgp/certificate_store/certificate/KeyMaterialReaderBackend.java +++ b/pgp-certificate-store/src/main/java/pgp/certificate_store/certificate/KeyMaterialReaderBackend.java @@ -15,6 +15,7 @@ public interface KeyMaterialReaderBackend { * Read a {@link KeyMaterial} (either {@link Key} or {@link Certificate}) from the given {@link InputStream}. * * @param data input stream containing the binary representation of the key. + * @param tag tag for the key material. Might be null. * @return key or certificate object * * @throws IOException in case of an IO error