Allow specification of signature type

This commit is contained in:
Paul Schaub 2020-12-16 16:33:14 +01:00
parent aeed8bf705
commit 4870bda4f2
6 changed files with 47 additions and 15 deletions

View File

@ -35,6 +35,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.exception.SecretKeyNotFoundException;
import org.pgpainless.key.OpenPgpV4Fingerprint;
@ -54,6 +55,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
private OutputStream outputStream;
private final Set<PGPPublicKey> encryptionKeys = new HashSet<>();
private boolean detachedSignature = false;
private SignatureType signatureType = SignatureType.BINARY_DOCUMENT;
private final Set<PGPSecretKey> signingKeys = new HashSet<>();
private SecretKeyRingProtector signingKeysDecryptor;
private SymmetricKeyAlgorithm symmetricKeyAlgorithm = SymmetricKeyAlgorithm.AES_128;
@ -257,17 +259,17 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
}
@Override
public Armor signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKey... keys) {
public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKey... keys) {
return new SignWithImpl().signWith(decryptor, keys);
}
@Override
public Armor signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings) {
public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings) {
return new SignWithImpl().signWith(decryptor, keyRings);
}
@Override
public <O> Armor signWith(@Nonnull SecretKeyRingSelectionStrategy<O> selectionStrategy,
public <O> DocumentType signWith(@Nonnull SecretKeyRingSelectionStrategy<O> selectionStrategy,
@Nonnull SecretKeyRingProtector decryptor,
@Nonnull MultiMap<O, PGPSecretKeyRingCollection> keys)
throws SecretKeyNotFoundException {
@ -278,7 +280,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
class SignWithImpl implements SignWith {
@Override
public Armor signWith(@Nonnull SecretKeyRingProtector decryptor,
public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor,
@Nonnull PGPSecretKey... keys) {
if (keys.length == 0) {
throw new IllegalArgumentException("Recipient list MUST NOT be empty.");
@ -291,11 +293,11 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
}
}
EncryptionBuilder.this.signingKeysDecryptor = decryptor;
return new ArmorImpl();
return new DocumentTypeImpl();
}
@Override
public Armor signWith(@Nonnull SecretKeyRingProtector decryptor,
public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor,
@Nonnull PGPSecretKeyRing... keys) {
if (keys.length == 0) {
throw new IllegalArgumentException("Recipient list MUST NOT be empty.");
@ -309,11 +311,11 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
}
}
EncryptionBuilder.this.signingKeysDecryptor = decryptor;
return new ArmorImpl();
return new DocumentTypeImpl();
}
@Override
public <O> Armor signWith(@Nonnull SecretKeyRingSelectionStrategy<O> ringSelectionStrategy,
public <O> DocumentType signWith(@Nonnull SecretKeyRingSelectionStrategy<O> ringSelectionStrategy,
@Nonnull SecretKeyRingProtector decryptor,
@Nonnull MultiMap<O, PGPSecretKeyRingCollection> keys) {
if (keys.isEmpty()) {
@ -332,6 +334,21 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
}
}
}
return new DocumentTypeImpl();
}
}
class DocumentTypeImpl implements DocumentType {
@Override
public Armor signBinaryDocument() {
EncryptionBuilder.this.signatureType = SignatureType.BINARY_DOCUMENT;
return new ArmorImpl();
}
@Override
public Armor signCanonicalText() {
EncryptionBuilder.this.signatureType = SignatureType.CANONICAL_TEXT_DOCUMENT;
return new ArmorImpl();
}
}
@ -363,6 +380,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
EncryptionBuilder.this.outputStream,
EncryptionBuilder.this.encryptionKeys,
EncryptionBuilder.this.detachedSignature,
signatureType,
privateKeys,
EncryptionBuilder.this.symmetricKeyAlgorithm,
EncryptionBuilder.this.hashAlgorithm,

View File

@ -181,7 +181,7 @@ public interface EncryptionBuilderInterface {
* @param keys secret keys
* @return api handle
*/
default Armor signWith(@Nonnull PGPSecretKey... keys) {
default DocumentType signWith(@Nonnull PGPSecretKey... keys) {
return signWith(new UnprotectedKeysProtector(), keys);
}
@ -193,7 +193,7 @@ public interface EncryptionBuilderInterface {
* @param keys secret keys used for signing
* @return api handle
*/
Armor signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKey... keys);
DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKey... keys);
/**
* Pass in a list of secret keys used for signing, along with a {@link SecretKeyRingProtector} used to unlock
@ -203,7 +203,7 @@ public interface EncryptionBuilderInterface {
* @param keyRings secret keys used for signing
* @return api handle
*/
Armor signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings);
DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings);
/**
* Pass in a map of secret keys for signing, as well as a {@link org.pgpainless.key.selection.key.SecretKeySelectionStrategy}
@ -218,13 +218,20 @@ public interface EncryptionBuilderInterface {
*
* @throws SecretKeyNotFoundException in case no suitable secret key can be found
*/
<O> Armor signWith(@Nonnull SecretKeyRingSelectionStrategy<O> selectionStrategy,
<O> DocumentType signWith(@Nonnull SecretKeyRingSelectionStrategy<O> selectionStrategy,
@Nonnull SecretKeyRingProtector decryptor,
@Nonnull MultiMap<O, PGPSecretKeyRingCollection> keys)
throws SecretKeyNotFoundException;
}
interface DocumentType {
Armor signBinaryDocument();
Armor signCanonicalText();
}
interface Armor {
/**

View File

@ -42,6 +42,7 @@ import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.DetachedSignature;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
@ -63,6 +64,7 @@ public final class EncryptionStream extends OutputStream {
private final CompressionAlgorithm compressionAlgorithm;
private final Set<PGPPublicKey> encryptionKeys;
private final boolean detachedSignature;
private final SignatureType signatureType;
private final Map<OpenPgpV4Fingerprint, PGPPrivateKey> signingKeys;
private final boolean asciiArmor;
@ -85,6 +87,7 @@ public final class EncryptionStream extends OutputStream {
EncryptionStream(@Nonnull OutputStream targetOutputStream,
@Nonnull Set<PGPPublicKey> encryptionKeys,
boolean detachedSignature,
SignatureType signatureType,
@Nonnull Map<OpenPgpV4Fingerprint, PGPPrivateKey> signingKeys,
@Nonnull SymmetricKeyAlgorithm symmetricKeyAlgorithm,
@Nonnull HashAlgorithm hashAlgorithm,
@ -97,6 +100,7 @@ public final class EncryptionStream extends OutputStream {
this.compressionAlgorithm = compressionAlgorithm;
this.encryptionKeys = Collections.unmodifiableSet(encryptionKeys);
this.detachedSignature = detachedSignature;
this.signatureType = signatureType;
this.signingKeys = Collections.unmodifiableMap(signingKeys);
this.asciiArmor = asciiArmor;
@ -156,7 +160,7 @@ public final class EncryptionStream extends OutputStream {
privateKey.getPublicKeyPacket().getAlgorithm(), hashAlgorithm.getAlgorithmId());
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
signatureGenerator.init(signatureType.getCode(), privateKey);
signatureGenerators.put(fingerprint, signatureGenerator);
}
}

View File

@ -142,6 +142,7 @@ public class EncryptDecryptTest {
.toRecipients(recipientPub)
.usingSecureAlgorithms()
.signWith(keyDecryptor, senderSec)
.signBinaryDocument()
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);
@ -197,6 +198,7 @@ public class EncryptDecryptTest {
.doNotEncrypt()
.createDetachedSignature()
.signWith(keyRingProtector, signingKeys)
.signBinaryDocument()
.noArmor();
Streams.pipeAll(inputStream, signer);
signer.close();
@ -238,6 +240,7 @@ public class EncryptDecryptTest {
EncryptionStream signer = PGPainless.encryptAndOrSign().onOutputStream(signOut)
.doNotEncrypt()
.signWith(keyRingProtector, signingKeys)
.signBinaryDocument()
.asciiArmor();
Streams.pipeAll(inputStream, signer);
signer.close();

View File

@ -26,7 +26,6 @@ import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
@ -96,7 +95,6 @@ public class LengthTest {
encryptDecryptForSecretKeyRings(sender, recipient);
}
@Ignore
private void encryptDecryptForSecretKeyRings(PGPSecretKeyRing senderSec, PGPSecretKeyRing recipientSec)
throws PGPException,
IOException {
@ -117,6 +115,7 @@ public class LengthTest {
// .doNotEncrypt()
.usingSecureAlgorithms()
.signWith(keyDecryptor, senderSec)
.signBinaryDocument()
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);

View File

@ -182,6 +182,7 @@ public class ChangeSecretKeyRingPassphraseTest {
EncryptionStream stream = PGPainless.encryptAndOrSign().onOutputStream(dummy)
.doNotEncrypt()
.signWith(PasswordBasedSecretKeyRingProtector.forKey(keyRing, passphrase), keyRing)
.signBinaryDocument()
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(dummyMessage.getBytes()), stream);