1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-30 08:12:06 +01:00

Allow the user to specify a purpose for encryption

This commit is contained in:
Paul Schaub 2021-01-09 20:30:34 +01:00
parent 8df752e995
commit 11c41e7ba7
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 67 additions and 4 deletions

View file

@ -66,12 +66,26 @@ public class PGPainless {
/** /**
* Create an {@link EncryptionStream}, which can be used to encrypt and/or sign data using OpenPGP. * Create an {@link EncryptionStream}, which can be used to encrypt and/or sign data using OpenPGP.
* This method assumes that the stream will be used to encrypt data for communication purposes.
* If you instead want to encrypt data that will be saved on disk (eg. a backup), use
* {@link #encryptAndOrSign(EncryptionStream.Purpose)} and chose an appropriate purpose.
*
* @return builder * @return builder
*/ */
public static EncryptionBuilder encryptAndOrSign() { public static EncryptionBuilder encryptAndOrSign() {
return new EncryptionBuilder(); return new EncryptionBuilder();
} }
/**
* Create an {@link EncryptionStream}, that can be used to encrypt and/or sign data using OpenPGP.
*
* @param purpose how will the data be used?
* @return builder
*/
public static EncryptionBuilder encryptAndOrSign(EncryptionStream.Purpose purpose) {
return new EncryptionBuilder(purpose);
}
/** /**
* Create a {@link DecryptionStream}, which can be used to decrypt and/or verify data using OpenPGP. * Create a {@link DecryptionStream}, which can be used to decrypt and/or verify data using OpenPGP.
* *

View file

@ -37,6 +37,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SignatureType; import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.exception.SecretKeyNotFoundException; import org.pgpainless.exception.SecretKeyNotFoundException;
@ -55,6 +56,7 @@ import org.pgpainless.util.Passphrase;
public class EncryptionBuilder implements EncryptionBuilderInterface { public class EncryptionBuilder implements EncryptionBuilderInterface {
private final EncryptionStream.Purpose purpose;
private OutputStream outputStream; private OutputStream outputStream;
private final Set<PGPPublicKey> encryptionKeys = new HashSet<>(); private final Set<PGPPublicKey> encryptionKeys = new HashSet<>();
private final Set<Passphrase> encryptionPassphrases = new HashSet<>(); private final Set<Passphrase> encryptionPassphrases = new HashSet<>();
@ -67,6 +69,14 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
private CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.UNCOMPRESSED; private CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.UNCOMPRESSED;
private boolean asciiArmor = false; private boolean asciiArmor = false;
public EncryptionBuilder() {
this.purpose = EncryptionStream.Purpose.COMMUNICATIONS;
}
public EncryptionBuilder(@Nonnull EncryptionStream.Purpose purpose) {
this.purpose = purpose;
}
@Override @Override
public ToRecipients onOutputStream(@Nonnull OutputStream outputStream) { public ToRecipients onOutputStream(@Nonnull OutputStream outputStream) {
this.outputStream = outputStream; this.outputStream = outputStream;
@ -425,9 +435,28 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
} }
PublicKeySelectionStrategy encryptionKeySelector() { PublicKeySelectionStrategy encryptionKeySelector() {
KeyFlag[] flags = mapPurposeToKeyFlags(purpose);
return new And.PubKeySelectionStrategy( return new And.PubKeySelectionStrategy(
new NoRevocation.PubKeySelectionStrategy(), new NoRevocation.PubKeySelectionStrategy(),
new EncryptionKeySelectionStrategy()); new EncryptionKeySelectionStrategy(flags));
}
private static KeyFlag[] mapPurposeToKeyFlags(EncryptionStream.Purpose purpose) {
KeyFlag[] flags;
switch (purpose) {
case COMMUNICATIONS:
flags = new KeyFlag[] {KeyFlag.ENCRYPT_COMMS};
break;
case STORAGE:
flags = new KeyFlag[] {KeyFlag.ENCRYPT_STORAGE};
break;
case STORAGE_AND_COMMUNICATIONS:
flags = new KeyFlag[] {KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE};
break;
default:
throw new AssertionError("Illegal purpose enum value encountered.");
}
return flags;
} }
SecretKeySelectionStrategy signingKeySelector() { SecretKeySelectionStrategy signingKeySelector() {

View file

@ -59,6 +59,23 @@ import org.pgpainless.util.Passphrase;
*/ */
public final class EncryptionStream extends OutputStream { public final class EncryptionStream extends OutputStream {
public enum Purpose {
/**
* The stream will encrypt communication that goes over the wire.
* Eg. EMail, Chat...
*/
COMMUNICATIONS,
/**
* The stream will encrypt data that is stored on disk.
* Eg. Encrypted backup...
*/
STORAGE,
/**
* The stream will use keys with either flags to encrypt the data.
*/
STORAGE_AND_COMMUNICATIONS
}
private static final Logger LOGGER = Logger.getLogger(EncryptionStream.class.getName()); private static final Logger LOGGER = Logger.getLogger(EncryptionStream.class.getName());
private static final Level LEVEL = Level.FINE; private static final Level LEVEL = Level.FINE;

View file

@ -26,11 +26,14 @@ import org.pgpainless.key.selection.key.PublicKeySelectionStrategy;
*/ */
public class EncryptionKeySelectionStrategy extends PublicKeySelectionStrategy { public class EncryptionKeySelectionStrategy extends PublicKeySelectionStrategy {
private static final HasKeyFlagSelectionStrategy.PublicKey HAS_ENCRYPT_COMMS_FLAG = private final HasKeyFlagSelectionStrategy.PublicKey keyFlagSelector;
new HasKeyFlagSelectionStrategy.PublicKey(KeyFlag.ENCRYPT_COMMS);
public EncryptionKeySelectionStrategy(KeyFlag... flags) {
this.keyFlagSelector = new HasKeyFlagSelectionStrategy.PublicKey(flags);
}
@Override @Override
public boolean accept(@Nonnull PGPPublicKey key) { public boolean accept(@Nonnull PGPPublicKey key) {
return key.isEncryptionKey() && HAS_ENCRYPT_COMMS_FLAG.accept(key); return key.isEncryptionKey() && keyFlagSelector.accept(key);
} }
} }