1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-12 19:59:38 +02:00

Compare commits

...

29 commits
main ... 1.3.18

Author SHA1 Message Date
ccfe126eb9
PGPainless 1.3.18 2023-11-23 13:21:59 +01:00
4061e2033c
Update changelog 2023-11-23 13:20:18 +01:00
97e85d6d8b
Bump sop-java to 4.1.2 2023-11-23 13:19:01 +01:00
182430e461
Remove test with expired key material 2023-11-23 13:18:50 +01:00
8ca8bebb41
PGPainless 1.3.18-SNAPSHOT 2023-06-10 14:28:51 +02:00
d698cde7d5
PGPainless 1.3.17 2023-06-10 14:25:19 +02:00
294efbca25
Update changelog 2023-06-10 14:23:56 +02:00
0ad5df76f8
Fix faulty bit-strength policy check for signing subkeys 2023-06-10 14:20:49 +02:00
a0a3d59cec
Direct-Key signatures are calculated over the signee only, not the signer plus signee 2023-06-10 14:20:36 +02:00
48a323441a
PGPainless 1.3.17-SNAPSHOT 2023-01-21 19:25:35 +01:00
b942cb8747
PGPainless 1.3.16 2023-01-21 19:23:22 +01:00
a056dc9881
Update changelog 2023-01-21 19:16:39 +01:00
9a4c24d822
Bump sop-java to 4.1.0 2023-01-21 19:12:33 +01:00
9022c27438 Bump gradlew to 7.5 2023-01-21 19:10:22 +01:00
b8c10d4c53
Fix typo in changelog 2022-12-15 17:49:51 +01:00
cdc3bdd9ef
PGPainless 1.3.16-SNAPSHOT 2022-12-15 17:43:37 +01:00
ebd6a7d2ae
PGPainless 1.3.15 2022-12-15 17:41:22 +01:00
b54ebb22c4
Update changelog 2022-12-15 17:38:06 +01:00
b6724d485c SOP: Allow generation of keys without user-ids 2022-12-15 14:47:20 +01:00
19e484b552 Cleartext-signatures MUST use TEXT mode 2022-12-15 14:43:56 +01:00
8e768636c8
Add regression test for #351 2022-12-15 12:30:30 +01:00
05ae631a12
Fix NPE when sop generate-key --with-key-password is used with multiple uids
Fixes #351
2022-12-15 12:25:35 +01:00
43a29729ad
Add hints about usage of deprecated methods 2022-12-15 12:20:28 +01:00
93208ee7bb
PGPainless 1.3.15-SNAPSHOT 2022-12-13 16:28:08 +01:00
65a8946923
PGPainless 1.3.14 2022-12-13 16:25:44 +01:00
5b6158d64b
Bump bcpg to 1.72.3 2022-12-13 16:24:56 +01:00
58c3afae3e
Update changelog 2022-12-13 16:15:56 +01:00
9a52f0e0aa
Fix parameter check for DSA keys
Fixes #345
2022-12-13 16:15:32 +01:00
fad5603c69
Use proper method to unlock private key when detached-signing 2022-12-13 16:11:17 +01:00
17 changed files with 394 additions and 331 deletions

View file

@ -5,6 +5,28 @@ SPDX-License-Identifier: CC0-1.0
# PGPainless Changelog
## 1.3.18
- Bump `sop-java` to `4.1.2`
- Fix `decrypt --verify-with XYZ` not throwing `NoSignature` exception (exit code 3) if `VERIFICATIONS` is empty (#415)
## 1.3.17
- Bugfix: Direct-Key signatures are calculated over the signee key only, not the signer key + signee key
- Security: Fix faulty bit-strength policy check for signing subkeys
## 1.3.16
- Bump `sop-java` to `4.1.0`
- Bump `gradlew` to `7.5`
## 1.3.15
- Fix crash in `sop generate-key --with-key-password` when more than one user-id is given
- `sop generate-key`: Allow key generation without user-ids
- `sop inline-sign --as=clearsigned`: Make signatures of type 'text' instead of 'binary'
## 1.3.14
- Bump `bcpg` to `1.72.3`
- Fix DSA key parameter check
- Use proper method to unlock private signing keys when creating detached signatures
## 1.3.13
- Bump `sop-java` to `4.0.7`

View file

@ -191,7 +191,7 @@ repositories {
}
dependencies {
implementation 'org.pgpainless:pgpainless-core:1.3.13'
implementation 'org.pgpainless:pgpainless-core:1.3.18'
}
```

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-rc-1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -287,6 +287,7 @@ public class ConsumerOptions {
* @return options
*/
@Deprecated
// Is used to be compatible with legacy systems
public ConsumerOptions setIgnoreMDCErrors(boolean ignoreMDCErrors) {
this.ignoreMDCErrors = ignoreMDCErrors;
return this;

View file

@ -245,6 +245,7 @@ public final class ProducerOptions {
* @deprecated options other than the default value of {@link StreamEncoding#BINARY} are discouraged.
*/
@Deprecated
// is used to be compatible with legacy systems
public ProducerOptions setEncoding(@Nonnull StreamEncoding encoding) {
this.encodingField = encoding;
return this;

View file

@ -359,8 +359,7 @@ public final class SigningOptions {
if (signingSecKey == null) {
throw new KeyException.MissingSecretKeyException(OpenPgpFingerprint.of(secretKey), signingPubKey.getKeyID());
}
PGPPrivateKey signingSubkey = signingSecKey.extractPrivateKey(
secretKeyDecryptor.getDecryptor(signingPubKey.getKeyID()));
PGPPrivateKey signingSubkey = UnlockSecretKey.unlockSecretKey(signingSecKey, secretKeyDecryptor);
Set<HashAlgorithm> hashAlgorithms = userId != null ? keyRingInfo.getPreferredHashAlgorithms(userId)
: keyRingInfo.getPreferredHashAlgorithms(signingPubKey.getKeyID());
HashAlgorithm hashAlgorithm = negotiateHashAlgorithm(hashAlgorithms, PGPainless.getPolicy());
@ -380,7 +379,7 @@ public final class SigningOptions {
SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(secretKey, signingSubkey.getKeyID());
PGPSecretKey signingSecretKey = secretKey.getSecretKey(signingSubkey.getKeyID());
PublicKeyAlgorithm publicKeyAlgorithm = PublicKeyAlgorithm.requireFromId(signingSecretKey.getPublicKey().getAlgorithm());
int bitStrength = secretKey.getPublicKey().getBitStrength();
int bitStrength = signingSecretKey.getPublicKey().getBitStrength();
if (!PGPainless.getPolicy().getPublicKeyAlgorithmPolicy().isAcceptable(publicKeyAlgorithm, bitStrength)) {
throw new KeyException.UnacceptableSigningKeyException(
new KeyException.PublicKeyAlgorithmPolicyException(

View file

@ -7,6 +7,7 @@ package org.pgpainless.key.generation;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
@ -38,9 +39,9 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull UserId userId, @Nonnull RsaLength length)
public PGPSecretKeyRing simpleRsaKeyRing(@Nullable UserId userId, @Nonnull RsaLength length)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleRsaKeyRing(userId.toString(), length);
return simpleRsaKeyRing(userId == null ? null : userId.toString(), length);
}
/**
@ -56,7 +57,7 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length)
public PGPSecretKeyRing simpleRsaKeyRing(@Nullable String userId, @Nonnull RsaLength length)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleRsaKeyRing(userId, length, Passphrase.emptyPassphrase());
}
@ -75,9 +76,9 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull UserId userId, @Nonnull RsaLength length, String password)
public PGPSecretKeyRing simpleRsaKeyRing(@Nullable UserId userId, @Nonnull RsaLength length, @Nullable String password)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleRsaKeyRing(userId.toString(), length, password);
return simpleRsaKeyRing(userId == null ? null : userId.toString(), length, password);
}
/**
@ -94,7 +95,7 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length, String password)
public PGPSecretKeyRing simpleRsaKeyRing(@Nullable String userId, @Nonnull RsaLength length, @Nullable String password)
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
Passphrase passphrase = Passphrase.emptyPassphrase();
if (!isNullOrEmpty(password)) {
@ -103,12 +104,14 @@ public final class KeyRingTemplates {
return simpleRsaKeyRing(userId, length, passphrase);
}
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length, @Nonnull Passphrase passphrase)
public PGPSecretKeyRing simpleRsaKeyRing(@Nullable String userId, @Nonnull RsaLength length, @Nonnull Passphrase passphrase)
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
KeyRingBuilder builder = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS))
.addUserId(userId)
.setPassphrase(passphrase);
if (userId != null) {
builder.addUserId(userId);
}
return builder.build();
}
@ -125,9 +128,9 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleEcKeyRing(@Nonnull UserId userId)
public PGPSecretKeyRing simpleEcKeyRing(@Nullable UserId userId)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleEcKeyRing(userId.toString());
return simpleEcKeyRing(userId == null ? null : userId.toString());
}
/**
@ -143,7 +146,7 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleEcKeyRing(@Nonnull String userId)
public PGPSecretKeyRing simpleEcKeyRing(@Nullable String userId)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleEcKeyRing(userId, Passphrase.emptyPassphrase());
}
@ -162,9 +165,9 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleEcKeyRing(@Nonnull UserId userId, String password)
public PGPSecretKeyRing simpleEcKeyRing(@Nullable UserId userId, String password)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
return simpleEcKeyRing(userId.toString(), password);
return simpleEcKeyRing(userId == null ? null : userId.toString(), password);
}
/**
@ -181,7 +184,7 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing simpleEcKeyRing(@Nonnull String userId, String password)
public PGPSecretKeyRing simpleEcKeyRing(@Nullable String userId, String password)
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
Passphrase passphrase = Passphrase.emptyPassphrase();
if (!isNullOrEmpty(password)) {
@ -190,13 +193,15 @@ public final class KeyRingTemplates {
return simpleEcKeyRing(userId, passphrase);
}
public PGPSecretKeyRing simpleEcKeyRing(@Nonnull String userId, @Nonnull Passphrase passphrase)
public PGPSecretKeyRing simpleEcKeyRing(@Nullable String userId, @Nonnull Passphrase passphrase)
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
KeyRingBuilder builder = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA))
.addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
.addUserId(userId)
.setPassphrase(passphrase);
if (userId != null) {
builder.addUserId(userId);
}
return builder.build();
}
@ -211,8 +216,8 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing modernKeyRing(String userId) throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
return modernKeyRing(userId, (Passphrase) null);
public PGPSecretKeyRing modernKeyRing(@Nullable String userId) throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
return modernKeyRing(userId, Passphrase.emptyPassphrase());
}
/**
@ -227,21 +232,21 @@ public final class KeyRingTemplates {
* @throws NoSuchAlgorithmException in case of missing algorithm implementation in the crypto provider
* @throws PGPException in case of an OpenPGP related error
*/
public PGPSecretKeyRing modernKeyRing(String userId, String password)
public PGPSecretKeyRing modernKeyRing(@Nullable String userId, @Nullable String password)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
Passphrase passphrase = (password != null ? Passphrase.fromPassword(password) : null);
Passphrase passphrase = (password != null ? Passphrase.fromPassword(password) : Passphrase.emptyPassphrase());
return modernKeyRing(userId, passphrase);
}
public PGPSecretKeyRing modernKeyRing(String userId, Passphrase passphrase)
public PGPSecretKeyRing modernKeyRing(@Nullable String userId, @Nonnull Passphrase passphrase)
throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
KeyRingBuilder builder = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER))
.addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
.addSubkey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA))
.addUserId(userId);
if (passphrase != null && !passphrase.isEmpty()) {
builder.setPassphrase(passphrase);
.setPassphrase(passphrase);
if (userId != null) {
builder.addUserId(userId);
}
return builder.build();
}

View file

@ -195,7 +195,7 @@ public class PublicKeyParameterValidationUtil {
}
// q > 160 bits
boolean qLarge = pQ.getLowestSetBit() > 160;
boolean qLarge = pQ.bitLength() > 160;
if (!qLarge) {
return false;
}

View file

@ -43,11 +43,7 @@ public class ThirdPartyDirectKeySignatureBuilder extends AbstractSignatureBuilde
public PGPSignature build(PGPPublicKey key) throws PGPException {
PGPSignatureGenerator signatureGenerator = buildAndInitSignatureGenerator();
if (key.getKeyID() != publicSigningKey.getKeyID()) {
return signatureGenerator.generateCertification(publicSigningKey, key);
} else {
return signatureGenerator.generateCertification(key);
}
return signatureGenerator.generateCertification(key);
}
@Override

View file

@ -535,10 +535,10 @@ public abstract class SignatureValidator {
try {
signature.init(ImplementationFactory.getInstance().getPGPContentVerifierBuilderProvider(), signer);
boolean valid;
if (signer.getKeyID() != signee.getKeyID()) {
valid = signature.verifyCertification(signer, signee);
} else {
if (signer.getKeyID() == signee.getKeyID() || signature.getSignatureType() == PGPSignature.DIRECT_KEY) {
valid = signature.verifyCertification(signee);
} else {
valid = signature.verifyCertification(signer, signee);
}
if (!valid) {
throw new SignatureValidationException("Signature is not correct.");

View file

@ -1,272 +0,0 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <info@pgpainless.org>
//
// SPDX-License-Identifier: Apache-2.0
package investigations;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.MessageInspector;
import org.pgpainless.encryption_signing.EncryptionOptions;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.encryption_signing.SigningOptions;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.implementation.JceImplementationFactory;
import org.pgpainless.key.protection.SecretKeyRingProtector;
public class KleopatraCompatibilityTest {
public static final String KLEOPATRA_PUBKEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
"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\n" +
"g94JEXpwhb9guKuzYzP/QeBp4qFu5FO87w==\n" +
"=Jz7i\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
public static final String KLEOPATRA_SECKEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
"\n" +
"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\n" +
"=cgLL\n" +
"-----END PGP PRIVATE KEY BLOCK-----\n";
// signed and encrypted
public static final String KLEOPATRA_MESSAGE = "-----BEGIN PGP MESSAGE-----\n" +
"\n" +
"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\n" +
"=MgH4\n" +
"-----END PGP MESSAGE-----\n";
public static final String PGPAINLESS_MESSAGE = "-----BEGIN PGP MESSAGE-----\n" +
"Version: PGPainless\n" +
"\n" +
"hQGMA2gglaIyvWSdAQv/Y9Wx763qAM95+teCUPPNRc5Iwqbc5uFjxfbcwsHIWdiZ\n" +
"n2wHNUmd2dUqYgpqOcBwZ/fUJuoHj/uXKZ1pbz2QSVYaL9MulKpgWiVAo0K2w0Oc\n" +
"97KfZ0d66tcZIhslVpZW06+lXuwMyjjjExe32fAkPFnYyTNORljyYlb/RDSkh7Ke\n" +
"Q+48fLR2kitV0WyRZ+d9cMfx2+D2gWYiaFGek9SrhI8L+nNd4UKvM4K4sSq4JHYf\n" +
"DCxGPWYOaTculuX8dfDh3ftHbrmL2Ca7Iv4NB0kSduG8Gin2OWyeSIPIwpF2ci9g\n" +
"cIBssAYhmS88FQit5pW9z2RZ/e9XmYIP++kz3/EdI6DqkiPUv1fiHTrJBC93LvVg\n" +
"pq75h9RNFuUlqR09SVuB/uZB6tYgv77vy5lPFo+wmLjM41aS4+qI1hBI3Ym4XTc1\n" +
"spPA0sEHtQTQ/xRNYqGpwunJniMF3ukWpOB6UNvQld+p2lj8czexhEAcne1cjey/\n" +
"f0/WUnluSt0HIg8Mnd7s0ukBhb4YxjvARjuqi6PikGz4JPshRwB8dPtS9FQiRxL7\n" +
"obaPHXlmLwohEtT3akzoIj/9C3Y7qnfreSllDgRDxRVFPXy5QnQqpsTy2JuJ4cvo\n" +
"p55RE2kyJ3vBZlB6T53pSgC00hQnNxoqgy7aejRItlec7zx5DnEg8t4rA7LYEGLT\n" +
"MBLWbTRc/njH6GTyc/3x7j9k8V83exqpF6fXrE3GP1C3fBxHY2S9/5BFAlzimplz\n" +
"Mow4S15D04EllRRk6f9HKY598xS4QlDEW/f3utwkQ8+/lNqesVuV8n76WDldMv2O\n" +
"5gTqAZ/pKhDKRLY6km4B2+2IAt2zg+V141wryHJgE/4VyUbu7zZxDIcDouuATQvt\n" +
"wNMnntqy3NTbM7DefSiYe9IUsTUz/g0VQJikoJx+rdX6YzQnRk/cmwvELnskQjSk\n" +
"aGd92A4ousaM299IOkbpLvFaJdrs7cLH0rEQTG5S3tRJSLEnjr94BUVtpIhQDo3i\n" +
"455UahKcCx/KhyIzo+8OdH0TYZf5ZFGLdTrqgi0ybAHcLrXkM+g2JOsst99CeRUq\n" +
"f/T4oFvuDSlLU56iWlLVE7gvDBibXfWIJ65YBHY4ueEzBC/3xOVj+dmTM2JfUSX7\n" +
"mqD25NaDCOuN4WhJmZHC1wyipj3KYT2bLg4gasHr/LvEI+Df/DREdXtrYAqPqZYU\n" +
"0QuubMF4n3hMqmu2wA==\n" +
"=fMRM\n" +
"-----END PGP MESSAGE-----";
@Test
public void testMessageDecryptionAndVerification() throws PGPException, IOException {
ImplementationFactory.setFactoryImplementation(new JceImplementationFactory());
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KLEOPATRA_SECKEY);
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(KLEOPATRA_PUBKEY);
ConsumerOptions options = new ConsumerOptions()
.addDecryptionKey(secretKeys)
.addVerificationCert(publicKeys);
ByteArrayOutputStream out = new ByteArrayOutputStream();
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(KLEOPATRA_MESSAGE.getBytes(StandardCharsets.UTF_8)))
.withOptions(options);
Streams.pipeAll(decryptionStream, out);
decryptionStream.close();
}
@Test
public void testEncryptAndSignMessage() throws PGPException, IOException {
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KLEOPATRA_SECKEY);
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(KLEOPATRA_PUBKEY);
ProducerOptions options = ProducerOptions.signAndEncrypt(
EncryptionOptions.encryptCommunications()
.addRecipient(publicKeys)
.overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.AES_128),
SigningOptions.get()
.addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), secretKeys, DocumentSignatureType.BINARY_DOCUMENT)
);
ByteArrayOutputStream out = new ByteArrayOutputStream();
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
.onOutputStream(out)
.withOptions(options);
ByteArrayInputStream in = new ByteArrayInputStream("Hallo, Welt!\n\n".getBytes(StandardCharsets.UTF_8));
Streams.pipeAll(in, encryptionStream);
encryptionStream.close();
}
@Test
public void testMessageInspection() throws PGPException, IOException {
MessageInspector.EncryptionInfo info = MessageInspector.determineEncryptionInfoForMessage(
new ByteArrayInputStream(KLEOPATRA_MESSAGE.getBytes(StandardCharsets.UTF_8)));
}
}

View file

@ -23,7 +23,7 @@ To start using pgpainless-sop in your code, include the following lines in your
...
dependencies {
...
implementation "org.pgpainless:pgpainless-sop:1.3.13"
implementation "org.pgpainless:pgpainless-sop:1.3.18"
...
}
@ -34,7 +34,7 @@ dependencies {
<dependency>
<groupId>org.pgpainless</groupId>
<artifactId>pgpainless-sop</artifactId>
<version>1.3.13</version>
<version>1.3.18</version>
</dependency>
...
</dependencies>

View file

@ -28,7 +28,7 @@ public class GenerateKeyImpl implements GenerateKey {
private boolean armor = true;
private final Set<String> userIds = new LinkedHashSet<>();
private Passphrase passphrase;
private Passphrase passphrase = Passphrase.emptyPassphrase();
@Override
public GenerateKey noArmor() {
@ -51,20 +51,18 @@ public class GenerateKeyImpl implements GenerateKey {
@Override
public Ready generate() throws SOPGPException.MissingArg, SOPGPException.UnsupportedAsymmetricAlgo {
Iterator<String> userIdIterator = userIds.iterator();
if (!userIdIterator.hasNext()) {
throw new SOPGPException.MissingArg("Missing user-id.");
}
Passphrase passphraseCopy = new Passphrase(passphrase.getChars()); // generateKeyRing clears the original passphrase
PGPSecretKeyRing key;
try {
String primaryUserId = userIdIterator.hasNext() ? userIdIterator.next() : null;
key = PGPainless.generateKeyRing()
.modernKeyRing(userIdIterator.next(), passphrase);
.modernKeyRing(primaryUserId, passphrase);
if (userIdIterator.hasNext()) {
SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(key);
while (userIdIterator.hasNext()) {
editor.addUserId(userIdIterator.next(), SecretKeyRingProtector.unprotectedKeys());
editor.addUserId(userIdIterator.next(), SecretKeyRingProtector.unlockAnyKeyWith(passphraseCopy));
}
key = editor.done();

View file

@ -75,7 +75,7 @@ public class InlineSignImpl implements InlineSign {
for (PGPSecretKeyRing key : signingKeys) {
try {
if (mode == InlineSignAs.clearsigned) {
signingOptions.addDetachedSignature(protector, key);
signingOptions.addDetachedSignature(protector, key, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT);
} else {
signingOptions.addInlineSignature(protector, key, modeToSigType(mode));
}

View file

@ -0,0 +1,295 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.sop;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import sop.ByteArrayAndResult;
import sop.DecryptionResult;
import sop.Ready;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CarolKeySignEncryptRoundtripTest {
private static final String CAROL_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
"\n" +
"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\n" +
"1FkOSekLi8WNMdUx3XMyvP8nJ65P2Q==\n" +
"=Xj8h\n" +
"-----END PGP PRIVATE KEY BLOCK-----\n";
private static final String CAROL_CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
"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\n" +
"=pa/S\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
private static final String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
"Comment: Bob's OpenPGP Transferable Secret Key\n" +
"\n" +
"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\n" +
"=miES\n" +
"-----END PGP PRIVATE KEY BLOCK-----\n";
private static final String BOB_CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"Comment: Bob's OpenPGP certificate\n" +
"\n" +
"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\n" +
"NEJd3XZRzaXZE2aAMQ==\n" +
"=NXei\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
@Test
public void regressionTest() throws IOException {
SOPImpl sop = new SOPImpl();
byte[] msg = "Hello, World!\n".getBytes();
Ready encryption = sop.encrypt()
.signWith(CAROL_KEY.getBytes())
.withCert(BOB_CERT.getBytes())
.plaintext(msg);
byte[] ciphertext = encryption.getBytes();
ByteArrayAndResult<DecryptionResult> decryption = sop.decrypt()
.withKey(BOB_KEY.getBytes())
.verifyWithCert(CAROL_CERT.getBytes())
.ciphertext(ciphertext)
.toByteArrayAndResult();
byte[] plaintext = decryption.getBytes();
assertArrayEquals(msg, plaintext);
assertEquals(1, decryption.getResult().getVerifications().size());
}
}

View file

@ -6,18 +6,21 @@ package org.pgpainless.sop;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.UnlockSecretKey;
import org.pgpainless.util.Passphrase;
import sop.SOP;
import sop.exception.SOPGPException;
public class GenerateKeyTest {
@ -28,11 +31,6 @@ public class GenerateKeyTest {
sop = new SOPImpl();
}
@Test
public void testMissingUserId() {
assertThrows(SOPGPException.MissingArg.class, () -> sop.generateKey().generate());
}
@Test
public void generateKey() throws IOException {
byte[] bytes = sop.generateKey()
@ -74,4 +72,24 @@ public class GenerateKeyTest {
assertFalse(new String(bytes).startsWith("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
}
@Test
public void protectedMultiUserIdKey() throws IOException, PGPException {
byte[] bytes = sop.generateKey()
.userId("Alice")
.userId("Bob")
.withKeyPassword("sw0rdf1sh")
.generate()
.getBytes();
PGPSecretKeyRing secretKey = PGPainless.readKeyRing().secretKeyRing(bytes);
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
assertTrue(info.getUserIds().contains("Alice"));
assertTrue(info.getUserIds().contains("Bob"));
for (PGPSecretKey key : secretKey) {
assertNotNull(UnlockSecretKey.unlockSecretKey(key, Passphrase.fromPassword("sw0rdf1sh")));
}
}
}

View file

@ -4,8 +4,8 @@
allprojects {
ext {
shortVersion = '1.3.14'
isSnapshot = true
shortVersion = '1.3.18'
isSnapshot = false
pgpainlessMinAndroidSdk = 10
javaSourceCompatibility = 1.8
bouncyCastleVersion = '1.72'
@ -13,11 +13,11 @@ allprojects {
// unfortunately we rely on 1.72.1 or 1.72.3 for a patch for https://github.com/bcgit/bc-java/issues/1257
// which is a bug we introduced with a PR against BC :/ oops
// When bouncyCastleVersion is 1.71, bouncyPgVersion can simply be set to 1.71 as well.
bouncyPgVersion = '1.72.1'
bouncyPgVersion = '1.72.3'
junitVersion = '5.8.2'
logbackVersion = '1.2.11'
mockitoVersion = '4.5.1'
slf4jVersion = '1.7.36'
sopJavaVersion = '4.0.7'
sopJavaVersion = '4.1.2'
}
}