1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-23 04:42:06 +01:00

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

View file

@ -181,7 +181,7 @@ public interface EncryptionBuilderInterface {
* @param keys secret keys * @param keys secret keys
* @return api handle * @return api handle
*/ */
default Armor signWith(@Nonnull PGPSecretKey... keys) { default DocumentType signWith(@Nonnull PGPSecretKey... keys) {
return signWith(new UnprotectedKeysProtector(), keys); return signWith(new UnprotectedKeysProtector(), keys);
} }
@ -193,7 +193,7 @@ public interface EncryptionBuilderInterface {
* @param keys secret keys used for signing * @param keys secret keys used for signing
* @return api handle * @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 * 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 * @param keyRings secret keys used for signing
* @return api handle * @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} * 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 * @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 SecretKeyRingProtector decryptor,
@Nonnull MultiMap<O, PGPSecretKeyRingCollection> keys) @Nonnull MultiMap<O, PGPSecretKeyRingCollection> keys)
throws SecretKeyNotFoundException; throws SecretKeyNotFoundException;
} }
interface DocumentType {
Armor signBinaryDocument();
Armor signCanonicalText();
}
interface Armor { interface Armor {
/** /**

View file

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

View file

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

View file

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

View file

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