Skip to content

Commit ecd7051

Browse files
committed
Clean up API
1 parent 0716d02 commit ecd7051

File tree

4 files changed

+54
-144
lines changed

4 files changed

+54
-144
lines changed

pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPMessageGenerator.java

+34-83
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,9 @@
2020
import org.bouncycastle.openpgp.PGPPrivateKey;
2121
import org.bouncycastle.openpgp.PGPPublicKey;
2222
import org.bouncycastle.openpgp.PGPPublicKeyRing;
23-
import org.bouncycastle.openpgp.PGPSecretKey;
24-
import org.bouncycastle.openpgp.PGPSecretKeyRing;
2523
import org.bouncycastle.openpgp.PGPSignature;
2624
import org.bouncycastle.openpgp.PGPSignatureGenerator;
2725
import org.bouncycastle.openpgp.operator.PBEKeyEncryptionMethodGenerator;
28-
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
2926
import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder;
3027
import org.bouncycastle.openpgp.operator.PublicKeyKeyEncryptionMethodGenerator;
3128

@@ -35,9 +32,7 @@
3532
import java.util.ArrayList;
3633
import java.util.Date;
3734
import java.util.Iterator;
38-
import java.util.LinkedHashSet;
3935
import java.util.List;
40-
import java.util.Set;
4136
import java.util.Stack;
4237
import java.util.stream.Collectors;
4338

@@ -106,21 +101,9 @@ else if (configuration.recipients.isEmpty())
106101
private HashAlgorithmNegotiator hashAlgorithmNegotiator =
107102
(key, subkey) -> HashAlgorithmTags.SHA512;
108103

109-
private SubkeySelector encryptionKeySelector = certificate ->
110-
{
111-
List<OpenPGPCertificate.OpenPGPComponentKey> encryptionKeys = certificate.getEncryptionKeys();
112-
return encryptionKeys.stream()
113-
.map(OpenPGPCertificate.OpenPGPComponentKey::getKeyIdentifier)
114-
.collect(Collectors.toList());
115-
};
104+
private SubkeySelector encryptionKeySelector = OpenPGPCertificate::getEncryptionKeys;
116105

117-
private SubkeySelector signingKeySelector = certificate ->
118-
{
119-
List<OpenPGPCertificate.OpenPGPComponentKey> signingKeys = certificate.getSigningKeys();
120-
return signingKeys.stream()
121-
.map(OpenPGPCertificate.OpenPGPComponentKey::getKeyIdentifier)
122-
.collect(Collectors.toList());
123-
};
106+
private SubkeySelector signingKeySelector = OpenPGPCertificate::getSigningKeys;
124107

125108
// Literal Data metadata
126109
private Date fileModificationDate = null;
@@ -217,7 +200,7 @@ public OpenPGPMessageGenerator setHashAlgorithmNegotiator(HashAlgorithmNegotiato
217200
* @param recipientCertificate recipient certificate (public key)
218201
* @return this
219202
*/
220-
public OpenPGPMessageGenerator addEncryptionCertificate(PGPPublicKeyRing recipientCertificate)
203+
public OpenPGPMessageGenerator addEncryptionCertificate(OpenPGPCertificate recipientCertificate)
221204
{
222205
return addEncryptionCertificate(recipientCertificate, encryptionKeySelector);
223206
}
@@ -231,9 +214,9 @@ public OpenPGPMessageGenerator addEncryptionCertificate(PGPPublicKeyRing recipie
231214
* @param subkeySelector selector for encryption subkeys
232215
* @return this
233216
*/
234-
public OpenPGPMessageGenerator addEncryptionCertificate(PGPPublicKeyRing recipientCertificate, SubkeySelector subkeySelector)
217+
public OpenPGPMessageGenerator addEncryptionCertificate(OpenPGPCertificate recipientCertificate, SubkeySelector subkeySelector)
235218
{
236-
config.recipients.add(new Recipient(recipientCertificate, subkeySelector, implementation));
219+
config.recipients.add(new Recipient(recipientCertificate, subkeySelector));
237220
return this;
238221
}
239222

@@ -258,8 +241,8 @@ public OpenPGPMessageGenerator addEncryptionPassphrase(char[] passphrase)
258241
* @return this
259242
*/
260243
public OpenPGPMessageGenerator addSigningKey(
261-
PGPSecretKeyRing signingKey,
262-
PBESecretKeyDecryptorProvider signingKeyDecryptorProvider)
244+
OpenPGPKey signingKey,
245+
SecretKeyPassphraseProvider signingKeyDecryptorProvider)
263246
{
264247
return addSigningKey(signingKey, signingKeyDecryptorProvider, signingKeySelector);
265248
}
@@ -273,11 +256,11 @@ public OpenPGPMessageGenerator addSigningKey(
273256
* @return this
274257
*/
275258
public OpenPGPMessageGenerator addSigningKey(
276-
PGPSecretKeyRing signingKey,
277-
PBESecretKeyDecryptorProvider signingKeyDecryptorProvider,
259+
OpenPGPKey signingKey,
260+
SecretKeyPassphraseProvider signingKeyDecryptorProvider,
278261
SubkeySelector subkeySelector)
279262
{
280-
config.signingKeys.add(new Signer(signingKey, signingKeyDecryptorProvider, subkeySelector, implementation));
263+
config.signingKeys.add(new Signer(signingKey, signingKeyDecryptorProvider, subkeySelector));
281264
return this;
282265
}
283266

@@ -447,18 +430,16 @@ private void applySignatures(OpenPGPMessageOutputStream.Builder builder)
447430
Stack<PGPSignatureGenerator> signatureGenerators = new Stack<>();
448431
for (Signer s : config.signingKeys)
449432
{
450-
for (PGPSecretKey signingSubkey : s.signingSubkeys())
433+
for (OpenPGPKey.OpenPGPSecretKey signingSubkey : s.signingSubkeys())
451434
{
452435
int hashAlgorithm = hashAlgorithmNegotiator.negotiateHashAlgorithm(s.signingKey, signingSubkey);
453436
PGPSignatureGenerator sigGen = new PGPSignatureGenerator(
454-
implementation.pgpContentSignerBuilder(signingSubkey.getPublicKey().getAlgorithm(), hashAlgorithm),
455-
signingSubkey.getPublicKey());
456-
457-
PBESecretKeyDecryptor decryptor = s.decryptorProvider == null ? null :
458-
s.decryptorProvider.provideDecryptor(signingSubkey);
459-
PGPPrivateKey privKey = signingSubkey.extractPrivateKey(decryptor);
437+
implementation.pgpContentSignerBuilder(signingSubkey.getPGPSecretKey().getPublicKey().getAlgorithm(), hashAlgorithm),
438+
signingSubkey.getPGPSecretKey().getPublicKey());
439+
char[] passphrase = signingSubkey.isLocked() ? s.passphraseProvider.providePassphrase(signingSubkey) : null;
440+
PGPPrivateKey privateKey = signingSubkey.unlock(passphrase);
460441

461-
sigGen.init(PGPSignature.BINARY_DOCUMENT, privKey);
442+
sigGen.init(PGPSignature.BINARY_DOCUMENT, privateKey);
462443
signatureGenerators.push(sigGen);
463444
}
464445
}
@@ -561,7 +542,7 @@ public interface EncryptionNegotiator
561542

562543
public interface HashAlgorithmNegotiator
563544
{
564-
int negotiateHashAlgorithm(OpenPGPKey key, PGPSecretKey subkey);
545+
int negotiateHashAlgorithm(OpenPGPKey key, OpenPGPCertificate.OpenPGPComponentKey subkey);
565546
}
566547

567548
public static class Configuration
@@ -617,18 +598,11 @@ public Recipient(OpenPGPCertificate certificate, SubkeySelector subkeySelector)
617598
*/
618599
public List<PGPPublicKey> encryptionSubkeys()
619600
{
620-
// we first construct a set, so that we don't accidentally encrypt the message multiple times for the
621-
// same subkey (e.g. if wildcards KeyIdentifiers are used).
622-
Set<PGPPublicKey> encryptionKeys = new LinkedHashSet<>();
623-
for (KeyIdentifier identifier : subkeySelector.select(certificate))
624-
{
625-
Iterator<PGPPublicKey> selected = certificate.getPGPKeyRing().getPublicKeys(identifier);
626-
while (selected.hasNext())
627-
{
628-
encryptionKeys.add(selected.next());
629-
}
630-
}
631-
return new ArrayList<>(encryptionKeys);
601+
return subkeySelector.select(certificate)
602+
.stream()
603+
.map(OpenPGPCertificate.OpenPGPComponentKey::getPGPPublicKey)
604+
.distinct()
605+
.collect(Collectors.toList());
632606
}
633607
}
634608

@@ -638,48 +612,25 @@ public List<PGPPublicKey> encryptionSubkeys()
638612
static class Signer
639613
{
640614
private final OpenPGPKey signingKey;
641-
private final PBESecretKeyDecryptorProvider decryptorProvider;
615+
private final SecretKeyPassphraseProvider passphraseProvider;
642616
private final SubkeySelector subkeySelector;
643617

644-
/**
645-
* Create a {@link Signer}.
646-
*
647-
* @param signingKey OpenPGP key
648-
* @param decryptorProvider provider for decryptors to unlock the signing subkeys
649-
* @param subkeySelector selector to select the signing subkey
650-
*/
651-
public Signer(PGPSecretKeyRing signingKey,
652-
PBESecretKeyDecryptorProvider decryptorProvider,
653-
SubkeySelector subkeySelector,
654-
OpenPGPImplementation implementation)
655-
{
656-
this(new OpenPGPKey(signingKey, implementation),
657-
decryptorProvider, subkeySelector);
658-
}
659-
660618
public Signer(OpenPGPKey signingKey,
661-
PBESecretKeyDecryptorProvider decryptorProvider,
619+
SecretKeyPassphraseProvider passphraseProvider,
662620
SubkeySelector subkeySelector)
663621
{
664622
this.signingKey = signingKey;
665-
this.decryptorProvider = decryptorProvider;
623+
this.passphraseProvider = passphraseProvider;
666624
this.subkeySelector = subkeySelector;
667625
}
668626

669-
public List<PGPSecretKey> signingSubkeys()
627+
public List<OpenPGPKey.OpenPGPSecretKey> signingSubkeys()
670628
{
671-
// we first construct a set, so that we don't accidentally sign the message multiple times using the
672-
// same subkey (e.g. if wildcards KeyIdentifiers are used).
673-
Set<PGPSecretKey> signingKeys = new LinkedHashSet<>();
674-
for (KeyIdentifier identifier : subkeySelector.select(signingKey))
675-
{
676-
Iterator<PGPSecretKey> selected = signingKey.getPGPKeyRing().getSecretKeys(identifier);
677-
while (selected.hasNext())
678-
{
679-
signingKeys.add(selected.next());
680-
}
681-
}
682-
return new ArrayList<>(signingKeys);
629+
return subkeySelector.select(signingKey)
630+
.stream()
631+
.map(signingKey::getSecretKey)
632+
.distinct()
633+
.collect(Collectors.toList());
683634
}
684635
}
685636

@@ -806,11 +757,11 @@ public interface SubkeySelector
806757
* @param certificate OpenPGP key or certificate
807758
* @return non-null list of identifiers
808759
*/
809-
List<KeyIdentifier> select(OpenPGPCertificate certificate);
760+
List<OpenPGPCertificate.OpenPGPComponentKey> select(OpenPGPCertificate certificate);
810761
}
811762

812-
public interface PBESecretKeyDecryptorProvider
763+
public interface SecretKeyPassphraseProvider
813764
{
814-
PBESecretKeyDecryptor provideDecryptor(PGPSecretKey key);
765+
char[] providePassphrase(OpenPGPKey.OpenPGPSecretKey key);
815766
}
816767
}

pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPMessageGeneratorTest.java

+11-30
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
11
package org.bouncycastle.openpgp.api.test;
22

3-
import org.bouncycastle.bcpg.ArmoredInputStream;
4-
import org.bouncycastle.bcpg.BCPGInputStream;
53
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
64
import org.bouncycastle.bcpg.test.AbstractPacketTest;
75
import org.bouncycastle.openpgp.PGPException;
8-
import org.bouncycastle.openpgp.PGPObjectFactory;
9-
import org.bouncycastle.openpgp.PGPPublicKey;
10-
import org.bouncycastle.openpgp.PGPPublicKeyRing;
11-
import org.bouncycastle.openpgp.PGPSecretKeyRing;
6+
import org.bouncycastle.openpgp.api.BcOpenPGPImplementation;
7+
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
8+
import org.bouncycastle.openpgp.api.OpenPGPKey;
129
import org.bouncycastle.openpgp.api.OpenPGPMessageGenerator;
1310
import org.bouncycastle.openpgp.api.OpenPGPMessageOutputStream;
14-
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
1511
import org.bouncycastle.util.encoders.Hex;
1612

17-
import java.io.ByteArrayInputStream;
1813
import java.io.ByteArrayOutputStream;
1914
import java.io.IOException;
2015
import java.io.OutputStream;
2116
import java.nio.charset.StandardCharsets;
22-
import java.util.ArrayList;
23-
import java.util.Iterator;
24-
import java.util.List;
2517

2618
public class OpenPGPMessageGeneratorTest
2719
extends AbstractPacketTest
@@ -141,14 +133,10 @@ private void seipd2EncryptedMessage()
141133
"j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDEM0g12vYxoWM8Y81W+bHBw805\n" +
142134
"I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==\n" +
143135
"-----END PGP PUBLIC KEY BLOCK-----";
144-
ByteArrayInputStream bIn = new ByteArrayInputStream(v6Cert.getBytes(StandardCharsets.UTF_8));
145-
ArmoredInputStream aIn = new ArmoredInputStream(bIn);
146-
BCPGInputStream pIn = new BCPGInputStream(aIn);
147-
PGPObjectFactory objFac = new BcPGPObjectFactory(pIn);
148-
PGPPublicKeyRing publicKeys = (PGPPublicKeyRing) objFac.nextObject();
136+
OpenPGPCertificate cert = OpenPGPCertificate.fromAsciiArmor(v6Cert, new BcOpenPGPImplementation());
149137

150138
OpenPGPMessageGenerator gen = new OpenPGPMessageGenerator();
151-
gen.addEncryptionCertificate(publicKeys);
139+
gen.addEncryptionCertificate(cert);
152140

153141
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
154142
OutputStream encOut = gen.open(bOut);
@@ -158,8 +146,10 @@ private void seipd2EncryptedMessage()
158146
System.out.println(bOut);
159147
}
160148

161-
private void seipd1EncryptedMessage() throws IOException, PGPException {
162-
String v4Cert = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
149+
private void seipd1EncryptedMessage()
150+
throws IOException, PGPException
151+
{
152+
String v4Key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
163153
"Comment: Bob's OpenPGP Transferable Secret Key\n" +
164154
"\n" +
165155
"lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv\n" +
@@ -241,19 +231,10 @@ private void seipd1EncryptedMessage() throws IOException, PGPException {
241231
"xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=\n" +
242232
"=miES\n" +
243233
"-----END PGP PRIVATE KEY BLOCK-----\n";
244-
ByteArrayInputStream bIn = new ByteArrayInputStream(v4Cert.getBytes(StandardCharsets.UTF_8));
245-
ArmoredInputStream aIn = new ArmoredInputStream(bIn);
246-
BCPGInputStream pIn = new BCPGInputStream(aIn);
247-
PGPObjectFactory objFac = new BcPGPObjectFactory(pIn);
248-
PGPSecretKeyRing secretKeys = (PGPSecretKeyRing) objFac.nextObject();
249-
List<PGPPublicKey> pubKeys = new ArrayList<>();
250-
for (Iterator<PGPPublicKey> it = secretKeys.getPublicKeys(); it.hasNext(); ) {
251-
pubKeys.add(it.next());
252-
}
253-
PGPPublicKeyRing publicKeys = new PGPPublicKeyRing(pubKeys);
234+
OpenPGPKey key = OpenPGPKey.fromAsciiArmor(v4Key, new BcOpenPGPImplementation());
254235

255236
OpenPGPMessageGenerator gen = new OpenPGPMessageGenerator();
256-
gen.addEncryptionCertificate(publicKeys);
237+
gen.addEncryptionCertificate(key);
257238

258239
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
259240
OutputStream encOut = gen.open(bOut);

pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPMessageProcessorTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ private void roundTripV6KeyEncryptedMessage()
156156

157157
OpenPGPMessageGenerator gen = new OpenPGPMessageGenerator()
158158
.setArmored(true)
159-
.addEncryptionCertificate(key.getPGPPublicKeyRing())
159+
.addEncryptionCertificate(key)
160160
.setIsPadded(false);
161161

162162
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

0 commit comments

Comments
 (0)