mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-19 19:02:06 +01:00
Fix sop encrypt --sign-with allowing for protected keys
This commit is contained in:
parent
75455f1a3c
commit
d64e749f22
3 changed files with 43 additions and 14 deletions
|
@ -8,6 +8,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||
|
@ -23,6 +25,8 @@ import org.pgpainless.encryption_signing.ProducerOptions;
|
|||
import org.pgpainless.encryption_signing.SigningOptions;
|
||||
import org.pgpainless.exception.KeyException;
|
||||
import org.pgpainless.exception.WrongPassphraseException;
|
||||
import org.pgpainless.key.OpenPgpFingerprint;
|
||||
import org.pgpainless.key.info.KeyRingInfo;
|
||||
import org.pgpainless.util.Passphrase;
|
||||
import sop.Ready;
|
||||
import sop.enums.EncryptAs;
|
||||
|
@ -35,6 +39,7 @@ public class EncryptImpl implements Encrypt {
|
|||
EncryptionOptions encryptionOptions = new EncryptionOptions();
|
||||
SigningOptions signingOptions = null;
|
||||
MatchMakingSecretKeyRingProtector protector = new MatchMakingSecretKeyRingProtector();
|
||||
private final Set<PGPSecretKeyRing> signingKeys = new HashSet<>();
|
||||
|
||||
private EncryptAs encryptAs = EncryptAs.Binary;
|
||||
boolean armor = true;
|
||||
|
@ -63,23 +68,15 @@ public class EncryptImpl implements Encrypt {
|
|||
if (keys.size() != 1) {
|
||||
throw new SOPGPException.BadData(new AssertionError("Exactly one secret key at a time expected. Got " + keys.size()));
|
||||
}
|
||||
|
||||
PGPSecretKeyRing signingKey = keys.iterator().next();
|
||||
protector.addSecretKey(signingKey);
|
||||
|
||||
try {
|
||||
signingOptions.addInlineSignature(
|
||||
protector,
|
||||
signingKey,
|
||||
(encryptAs == EncryptAs.Binary ? DocumentSignatureType.BINARY_DOCUMENT : DocumentSignatureType.CANONICAL_TEXT_DOCUMENT)
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SOPGPException.KeyCannotSign();
|
||||
} catch (WrongPassphraseException e) {
|
||||
throw new SOPGPException.KeyIsProtected();
|
||||
} catch (PGPException e) {
|
||||
throw new SOPGPException.BadData(e);
|
||||
KeyRingInfo info = PGPainless.inspectKeyRing(signingKey);
|
||||
if (info.getSigningSubkeys().isEmpty()) {
|
||||
throw new SOPGPException.KeyCannotSign("Key " + OpenPgpFingerprint.of(signingKey) + " cannot sign.");
|
||||
}
|
||||
|
||||
protector.addSecretKey(signingKey);
|
||||
signingKeys.add(signingKey);
|
||||
} catch (IOException | PGPException e) {
|
||||
throw new SOPGPException.BadData(e);
|
||||
}
|
||||
|
@ -122,6 +119,22 @@ public class EncryptImpl implements Encrypt {
|
|||
producerOptions.setAsciiArmor(armor);
|
||||
producerOptions.setEncoding(encryptAsToStreamEncoding(encryptAs));
|
||||
|
||||
for (PGPSecretKeyRing signingKey : signingKeys) {
|
||||
try {
|
||||
signingOptions.addInlineSignature(
|
||||
protector,
|
||||
signingKey,
|
||||
(encryptAs == EncryptAs.Binary ? DocumentSignatureType.BINARY_DOCUMENT : DocumentSignatureType.CANONICAL_TEXT_DOCUMENT)
|
||||
);
|
||||
} catch (KeyException.UnacceptableSigningKeyException e) {
|
||||
throw new SOPGPException.KeyCannotSign();
|
||||
} catch (WrongPassphraseException e) {
|
||||
throw new SOPGPException.KeyIsProtected();
|
||||
} catch (PGPException e) {
|
||||
throw new SOPGPException.BadData(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ProxyOutputStream proxy = new ProxyOutputStream();
|
||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
||||
|
|
|
@ -38,6 +38,7 @@ public class EncryptDecryptRoundTripTest {
|
|||
sop = new SOPImpl();
|
||||
aliceKey = sop.generateKey()
|
||||
.userId("Alice <alice@pgpainless.org>")
|
||||
.withKeyPassword("wonderland.is.c00l")
|
||||
.generate()
|
||||
.getBytes();
|
||||
aliceCert = sop.extractCert()
|
||||
|
@ -56,6 +57,7 @@ public class EncryptDecryptRoundTripTest {
|
|||
public void basicRoundTripWithKey() throws IOException, SOPGPException.KeyCannotSign {
|
||||
byte[] encrypted = sop.encrypt()
|
||||
.signWith(aliceKey)
|
||||
.withKeyPassword("wonderland.is.c00l")
|
||||
.withCert(aliceCert)
|
||||
.withCert(bobCert)
|
||||
.plaintext(message)
|
||||
|
@ -426,6 +428,15 @@ public class EncryptDecryptRoundTripTest {
|
|||
assertArrayEquals(message, bytesAndResult.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptWithWrongPassphraseThrowsKeyIsProtected() {
|
||||
assertThrows(SOPGPException.KeyIsProtected.class, () -> sop.encrypt()
|
||||
.withKeyPassword("falsePassphrase")
|
||||
.signWith(aliceKey)
|
||||
.withCert(bobCert)
|
||||
.plaintext(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptionWithSessionKey_VerificationWithCert() throws IOException {
|
||||
byte[] plaintext = "This is a test message.\nSit back and relax.\n".getBytes(StandardCharsets.UTF_8);
|
||||
|
|
|
@ -64,4 +64,9 @@ public class IncapableKeysTest {
|
|||
assertThrows(SOPGPException.KeyCannotSign.class, () -> sop.detachedSign().key(nonSigningKey));
|
||||
assertThrows(SOPGPException.KeyCannotSign.class, () -> sop.inlineSign().key(nonSigningKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptAndSignWithNonSigningKeyFails() {
|
||||
assertThrows(SOPGPException.KeyCannotSign.class, () -> sop.encrypt().signWith(nonSigningKey));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue