1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-12-08 13:21:09 +01:00

Expose encryption mechanism during decryption

This commit is contained in:
Paul Schaub 2025-04-30 15:57:54 +02:00
parent 3cef99d256
commit 94febc33df
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 167 additions and 24 deletions

View file

@ -4,6 +4,7 @@
package org.pgpainless.decryption_verification;
import org.bouncycastle.openpgp.api.MessageEncryptionMechanism;
import org.junit.JUtils;
import org.junit.jupiter.api.Test;
import org.pgpainless.algorithm.CompressionAlgorithm;
@ -29,8 +30,8 @@ public class MessageMetadataTest {
MessageMetadata.Message message = new MessageMetadata.Message();
MessageMetadata.CompressedData compressedData = new MessageMetadata.CompressedData(CompressionAlgorithm.ZIP, message.getDepth() + 1);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(SymmetricKeyAlgorithm.AES_128, compressedData.getDepth() + 1);
MessageMetadata.EncryptedData encryptedData1 = new MessageMetadata.EncryptedData(SymmetricKeyAlgorithm.AES_256, encryptedData.getDepth() + 1);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(MessageEncryptionMechanism.integrityProtected(SymmetricKeyAlgorithm.AES_128.getAlgorithmId()), compressedData.getDepth() + 1);
MessageMetadata.EncryptedData encryptedData1 = new MessageMetadata.EncryptedData(MessageEncryptionMechanism.integrityProtected(SymmetricKeyAlgorithm.AES_256.getAlgorithmId()), encryptedData.getDepth() + 1);
MessageMetadata.LiteralData literalData = new MessageMetadata.LiteralData();
message.setChild(compressedData);

View file

@ -15,18 +15,25 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.MessageEncryptionMechanism;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.AEADAlgorithm;
import org.pgpainless.algorithm.AEADCipherMode;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.OpenPGPKeyVersion;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
@ -34,7 +41,11 @@ import org.pgpainless.decryption_verification.MessageMetadata;
import org.pgpainless.exception.KeyException;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.type.KeyType;
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve;
import org.pgpainless.key.generation.type.rsa.RsaLength;
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.util.ArmoredOutputStreamFactory;
@ -306,4 +317,74 @@ public class EncryptDecryptTest {
EncryptionOptions.encryptCommunications(api)
.addRecipient(publicKeys));
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testEncryptToOnlyV4CertWithOnlySEIPD1Feature() throws PGPException, IOException {
PGPainless api = PGPainless.getInstance();
OpenPGPKey v4Key = api.buildKey(OpenPGPKeyVersion.v4)
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.overridePreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm.AES_192)
.overrideFeatures(Feature.MODIFICATION_DETECTION)) // the key only supports SEIPD1
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE))
.build();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
EncryptionStream eOut = api.generateMessage().onOutputStream(bOut)
.withOptions(ProducerOptions.encrypt(EncryptionOptions.encryptCommunications()
.addRecipient(v4Key.toCertificate())));
eOut.write(testMessage.getBytes(StandardCharsets.UTF_8));
eOut.close();
ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
DecryptionStream dIn = PGPainless.decryptAndOrVerify()
.onInputStream(bIn)
.withOptions(ConsumerOptions.get().addDecryptionKey(v4Key));
bOut = new ByteArrayOutputStream();
Streams.pipeAll(dIn, bOut);
dIn.close();
assertEquals(testMessage, bOut.toString());
MessageMetadata metadata = dIn.getMetadata();
MessageEncryptionMechanism encryptionMechanism = metadata.getEncryptionMechanism();
assertEquals(
MessageEncryptionMechanism.integrityProtected(SymmetricKeyAlgorithm.AES_192.getAlgorithmId()),
encryptionMechanism);
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testEncryptToOnlyV6CertWithOnlySEIPD2Features() throws IOException, PGPException {
PGPainless api = PGPainless.getInstance();
OpenPGPKey v6Key = api.buildKey(OpenPGPKeyVersion.v6)
.setPrimaryKey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.overridePreferredAEADAlgorithms(new AEADCipherMode(AEADAlgorithm.OCB, SymmetricKeyAlgorithm.AES_128))
.overrideFeatures(Feature.MODIFICATION_DETECTION_2)) // the key only supports SEIPD2
.addSubkey(KeySpec.getBuilder(KeyType.X25519(), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE))
.build();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
EncryptionStream eOut = api.generateMessage().onOutputStream(bOut)
.withOptions(ProducerOptions.encrypt(EncryptionOptions.encryptCommunications()
.addRecipient(v6Key.toCertificate())));
eOut.write(testMessage.getBytes(StandardCharsets.UTF_8));
eOut.close();
ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
DecryptionStream dIn = PGPainless.decryptAndOrVerify()
.onInputStream(bIn)
.withOptions(ConsumerOptions.get().addDecryptionKey(v6Key));
bOut = new ByteArrayOutputStream();
Streams.pipeAll(dIn, bOut);
dIn.close();
assertEquals(testMessage, bOut.toString());
MessageMetadata metadata = dIn.getMetadata();
MessageEncryptionMechanism encryptionMechanism = metadata.getEncryptionMechanism();
assertEquals(
MessageEncryptionMechanism.aead(SymmetricKeyAlgorithm.AES_128.getAlgorithmId(), AEADAlgorithm.OCB.getAlgorithmId()),
encryptionMechanism);
}
}