mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-06-11 22:24:53 +02:00
88 lines
4.1 KiB
Java
88 lines
4.1 KiB
Java
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package org.pgpainless.decryption_verification;
|
|
|
|
import org.bouncycastle.openpgp.PGPException;
|
|
import org.bouncycastle.openpgp.PGPPrivateKey;
|
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
|
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
|
|
import org.bouncycastle.util.io.Streams;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.pgpainless.PGPainless;
|
|
import org.pgpainless.algorithm.EncryptionPurpose;
|
|
import org.pgpainless.encryption_signing.EncryptionOptions;
|
|
import org.pgpainless.encryption_signing.EncryptionStream;
|
|
import org.pgpainless.encryption_signing.ProducerOptions;
|
|
import org.pgpainless.key.SubkeyIdentifier;
|
|
import org.pgpainless.key.info.KeyRingInfo;
|
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
|
import org.pgpainless.util.Passphrase;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
public class CustomPublicKeyDataDecryptorFactoryTest {
|
|
|
|
@Test
|
|
public void testDecryptionWithEmulatedHardwareDecryptionCallback()
|
|
throws PGPException, IOException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
|
PGPSecretKeyRing secretKey = PGPainless.generateKeyRing().modernKeyRing("Alice");
|
|
PGPPublicKeyRing cert = PGPainless.extractCertificate(secretKey);
|
|
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
|
PGPPublicKey encryptionKey = info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
|
|
|
|
// Encrypt a test message
|
|
String plaintext = "Hello, World!\n";
|
|
ByteArrayOutputStream ciphertextOut = new ByteArrayOutputStream();
|
|
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
|
.onOutputStream(ciphertextOut)
|
|
.withOptions(ProducerOptions.encrypt(EncryptionOptions.get()
|
|
.addRecipient(cert)));
|
|
encryptionStream.write(plaintext.getBytes(StandardCharsets.UTF_8));
|
|
encryptionStream.close();
|
|
|
|
HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() {
|
|
@Override
|
|
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData)
|
|
throws HardwareSecurity.HardwareSecurityException {
|
|
// Emulate hardware decryption.
|
|
try {
|
|
PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID());
|
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase());
|
|
PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey);
|
|
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData});
|
|
} catch (PGPException e) {
|
|
throw new HardwareSecurity.HardwareSecurityException();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Decrypt
|
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
|
.onInputStream(new ByteArrayInputStream(ciphertextOut.toByteArray()))
|
|
.withOptions(ConsumerOptions.get()
|
|
.addCustomDecryptorFactory(
|
|
new HardwareSecurity.HardwareDataDecryptorFactory(
|
|
new SubkeyIdentifier(cert, encryptionKey.getKeyID()),
|
|
hardwareDecryptionCallback)));
|
|
|
|
ByteArrayOutputStream decryptedOut = new ByteArrayOutputStream();
|
|
Streams.pipeAll(decryptionStream, decryptedOut);
|
|
decryptionStream.close();
|
|
|
|
assertEquals(plaintext, decryptedOut.toString());
|
|
}
|
|
}
|