All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildDecryptionInputStreamAPI Maven / Gradle / Ivy

The newest version!
package name.neuhalfen.projects.crypto.bouncycastle.openpgp;

import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchProviderException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.decrypting.DecryptionStreamFactory;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.validation.SignatureValidationStrategies;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.validation.SignatureValidationStrategy;
import org.bouncycastle.openpgp.PGPException;

/**
 * This class implements the builder for decrypting GPG-encrypted streams.
 */
@SuppressWarnings({"PMD.AtLeastOneConstructor", "PMD.AccessorMethodGeneration", "PMD.LawOfDemeter"})
public final class BuildDecryptionInputStreamAPI {

  @Nonnull
  private KeyringConfig keyringConfig;
  @Nonnull
  private SignatureValidationStrategy signatureCheckingMode;

  /**
   * Start building by passing in the keyring config.
   *
   * @param keyringConfig Keyring
   *
   * @return next build step
   */
  @Nonnull
  public Validation withConfig(@Nullable KeyringConfig keyringConfig) {
    if (keyringConfig == null) {
      throw new IllegalArgumentException("keyringConfig must not be null");
    }

    BuildDecryptionInputStreamAPI.this.keyringConfig = keyringConfig;
    return new Validation();
  }

  public interface Build {

    /**
     * Build the final decrypted input stream.
     *
     * This method will start reading the cipherstream until it finds the encrypted plaintext.
     *
     * If the source data is NOT signed, but a signature is REQUIRED, then this function might
     * throw.
     *
     * Signatures are verified AFTER decryption (reading the whole(!) plaintext stream). In this
     * case the returned InputStream will validate the signatures.
     *
     * @param encryptedData An encrypted input stream. Will not be closed.
     *
     * @return Plaintext stream. Signatures are checked the moment EOF is reached.
     *
     * @throws IOException IO is dangerous. Also wraps several GPG exceptions.
     * @throws NoSuchProviderException BC provider is not registered
     */
    @Nonnull
    InputStream fromEncryptedInputStream(@Nullable InputStream encryptedData)
        throws IOException, NoSuchProviderException;
  }

  public final class Validation {

    /**
     * Decryption will enforce that the ciphertext has been signed by ALL of the public key ids
     * passed.
     *
     * Given  the following keyring:
     *
     * 
{@code markdown: text
     * $ gpg -k --keyid-format=0xlong
     *
     * ... pub 2048R/0x3DF16BD7C3F280F3 ... uid [ultimate] ...  
     * ... sub 2048R/0x54A3DB374F787AB7 ... [S] ... }
* * To require a valid signature from {@code [email protected]} with the following keyring, call * * {@code ...andRequireSignatureFromAllKeys(0x54A3DB374F787AB7L)}: * * @param publicKeyIds A valid signature from ALL of the passed keys is required. Each key MUST * exist in the public keyring. * * @return the next build step */ @Nonnull public Build andRequireSignatureFromAllKeys(@Nullable Long... publicKeyIds) { if (publicKeyIds == null || publicKeyIds.length == 0) { throw new IllegalArgumentException("publicKeyIds must not be null or empty"); } BuildDecryptionInputStreamAPI.this.signatureCheckingMode = SignatureValidationStrategies .requireSignatureFromAllKeys(publicKeyIds); return new Builder(); } /** * Decryption will enforce that the ciphertext has been signed by ALL of the public key ids * passed. * * Given the following keyring: * *
{@code markdown: text
     * $ gpg -k --keyid-format=0xlong
     *
     * ... pub 2048R/0x3DF16BD7C3F280F3 ... uid [ultimate] ...  
     * ... sub 2048R/0x54A3DB374F787AB7 ... [S] ... }
* * To require a valid signature from {@code [email protected]} with the following keyring, call * * {@code ...andRequireSignatureFromAllKeys("[email protected]")} * * @param userIds a valid signature from all of the passed keys is required. The keys MUST exist * in the public keyring. * * @return the next build step * * @throws PGPException error extracting public keys from keyring * @throws IOException IO is dangerous. Accessing the keyring might tough the filesystem. */ @Nonnull public Build andRequireSignatureFromAllKeys(@Nullable String... userIds) throws PGPException, IOException { if (userIds == null || userIds.length == 0) { throw new IllegalArgumentException("userIds must not be null or empty"); } BuildDecryptionInputStreamAPI.this.signatureCheckingMode = SignatureValidationStrategies .requireSignatureFromAllKeys(keyringConfig.getPublicKeyRings(), userIds); return new Builder(); } /** * Enforce a valid signature from *any* public key in the keyring. . Signatures of keys NOT * present in the keyring are IGNORED (treated as not existing). * * @return next build step */ @Nonnull public Build andValidateSomeoneSigned() { BuildDecryptionInputStreamAPI.this.signatureCheckingMode = SignatureValidationStrategies .requireAnySignature(); return new Builder(); } /** * Ignore all, even invalid(!) signatures. * * @return next build step */ @Nonnull public Build andIgnoreSignatures() { BuildDecryptionInputStreamAPI.this.signatureCheckingMode = SignatureValidationStrategies .ignoreSignatures(); return new Builder(); } public final class Builder implements Build { /** * Build the final decrypted input stream. . This method will start reading the cipherstream * until it finds the encrypted plaintext. . If the source data is NOT signed, but a signature * is REQUIRED, then this function might even throw. . Signatures are verified AFTER * decryption (reading the whole(!) plaintext stream). * * @param encryptedData An encrypted input stream. Will not be closed. * * @return Plaintext stream. Signatures are checked the moment EOF is reached. * * @throws IOException IO is dangerous. Also wraps several GPG exceptions. * @throws NoSuchProviderException BC provider is not registered */ @Nonnull public InputStream fromEncryptedInputStream(@Nullable InputStream encryptedData) throws IOException, NoSuchProviderException { if (encryptedData == null) { throw new IllegalArgumentException("encryptedData must not be null"); } final DecryptionStreamFactory pgpInputStreamFactory = DecryptionStreamFactory.create( BuildDecryptionInputStreamAPI.this.keyringConfig, BuildDecryptionInputStreamAPI.this.signatureCheckingMode); return pgpInputStreamFactory.wrapWithDecryptAndVerify(encryptedData); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy