1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-23 20:14:49 +02:00

Fix SOP encrypt-decrypt test

This commit is contained in:
Paul Schaub 2021-05-25 16:25:22 +02:00
parent b0692b4dc5
commit 3cd64b61ca
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
8 changed files with 88 additions and 72 deletions

View file

@ -112,7 +112,7 @@ public class KeyRingValidator {
}
}
} catch (SignatureValidationException e) {
LOGGER.log(Level.INFO, "Rejecting user-id certification for user-id " + userId, e);
LOGGER.log(Level.FINE, "Rejecting user-id certification for user-id " + userId, e);
}
}
}

View file

@ -269,7 +269,11 @@ public class KeyRingInfo {
public String getPrimaryUserId() {
String primaryUserId = null;
Date modificationDate = null;
for (String userId : getValidUserIds()) {
List<String> validUserIds = getValidUserIds();
if (validUserIds.isEmpty()) {
return null;
}
for (String userId : validUserIds) {
PGPSignature signature = signatures.userIdCertifications.get(userId);
PrimaryUserID subpacket = SignatureSubpacketsUtil.getPrimaryUserId(signature);
if (subpacket != null && subpacket.isPrimaryUserID()) {
@ -282,7 +286,7 @@ public class KeyRingInfo {
}
// Workaround for keys with only one user-id but no primary user-id packet.
if (primaryUserId == null) {
return getValidUserIds().get(0);
return validUserIds.get(0);
}
return primaryUserId;

View file

@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.bcpg.sig.SignerUserID;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
@ -123,7 +124,7 @@ public class SignatureChainValidator {
}
} catch (SignatureValidationException e) {
rejections.put(userIdSig, e);
LOGGER.log(Level.INFO, "Rejecting user-id signature.", e);
LOGGER.log(Level.FINE, "Rejecting user-id signature.", e);
}
}
Collections.sort(signaturesOnUserId, new SignatureValidityComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD));
@ -200,8 +201,18 @@ public class SignatureChainValidator {
throw new SignatureValidationException("Subkey is revoked.");
}
if (!KeyFlag.hasKeyFlag(SignatureSubpacketsUtil.getKeyFlags(currentSig).getFlags(), KeyFlag.SIGN_DATA)) {
throw new SignatureValidationException("Signature was made by key which is not capable of signing.");
KeyFlags keyFlags = SignatureSubpacketsUtil.getKeyFlags(currentSig);
if (keyFlags == null) {
if (directKeySignatures.isEmpty()) {
throw new SignatureValidationException("Signature was made by key which is not capable of signing (no keyflags on binding sig, no direct-key sig).");
}
PGPSignature directKeySig = directKeySignatures.get(0);
KeyFlags directKeyFlags = SignatureSubpacketsUtil.getKeyFlags(directKeySig);
if (!KeyFlag.hasKeyFlag(directKeyFlags.getFlags(), KeyFlag.SIGN_DATA)) {
throw new SignatureValidationException("Signature was made by key which is not capable of signing (no keyflags on binding sig, no SIGN flag on direct-key sig).");
}
} else if (!KeyFlag.hasKeyFlag(keyFlags.getFlags(), KeyFlag.SIGN_DATA)) {
throw new SignatureValidationException("Signature was made by key which is not capable of signing (no SIGN flag on binding sig).");
}
}
return true;

View file

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.pgpainless.PGPainless;
@ -41,4 +42,17 @@ public class SopKeyUtil {
}
return secretKeyRings;
}
public static List<PGPPublicKeyRing> loadCertificatesFromFile(File... files) throws IOException {
List<PGPPublicKeyRing> publicKeyRings = new ArrayList<>();
for (File file : files) {
try (FileInputStream in = new FileInputStream(file)) {
publicKeyRings.add(PGPainless.readKeyRing().publicKeyRing(in));
} catch (IOException e) {
err_ln("Could not read certificate from file " + file.getName() + ": " + e.getMessage());
throw e;
}
}
return publicKeyRings;
}
}

View file

@ -26,6 +26,7 @@ import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -40,7 +41,9 @@ import org.pgpainless.decryption_verification.DecryptionBuilderInterface;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.sop.SopKeyUtil;
import picocli.CommandLine;
import sun.text.resources.CollationData;
@CommandLine.Command(name = "decrypt",
description = "Decrypt a message from standard input",
@ -110,33 +113,27 @@ public class Decrypt implements Runnable {
}
PGPSecretKeyRingCollection secretKeys;
List<PGPPublicKeyRing> verifyWith = null;
try {
List<PGPSecretKeyRing> secretKeyRings = loadKeysFromFiles(keys);
secretKeys = new PGPSecretKeyRingCollection(secretKeyRings);
} catch (PGPException | IOException e) {
if (certs != null) {
verifyWith = SopKeyUtil.loadCertificatesFromFile(certs);
}
} catch (IOException | PGPException e) {
err_ln(e.getMessage());
System.exit(1);
return;
}
List<PGPPublicKeyRing> verifyWith = new ArrayList<>();
if (certs != null) {
for (File f : certs) {
try {
verifyWith.add(PGPainless.readKeyRing().publicKeyRing(new FileInputStream(f)));
} catch (IOException e) {
}
}
}
DecryptionBuilderInterface.Verify builder = PGPainless.decryptAndOrVerify()
.onInputStream(System.in)
.decryptWith(secretKeys);
DecryptionStream decryptionStream = null;
try {
if (certs != null) {
if (verifyWith != null) {
decryptionStream = builder.verifyWith(new HashSet<>(verifyWith))
.ignoreMissingPublicKeys().build();
} else {
@ -144,12 +141,14 @@ public class Decrypt implements Runnable {
.build();
}
} catch (IOException | PGPException e) {
err_ln("Error constructing decryption stream: " + e.getMessage());
System.exit(1);
return;
}
try {
Streams.pipeAll(decryptionStream, System.out);
System.out.flush();
decryptionStream.close();
} catch (IOException e) {
err_ln("Unable to decrypt: " + e.getMessage());
@ -161,28 +160,32 @@ public class Decrypt implements Runnable {
OpenPgpMetadata metadata = decryptionStream.getResult();
StringBuilder sb = new StringBuilder();
for (OpenPgpV4Fingerprint fingerprint : metadata.getVerifiedSignatures().keySet()) {
PGPPublicKeyRing verifier = null;
for (PGPPublicKeyRing ring : verifyWith) {
if (ring.getPublicKey(fingerprint.getKeyId()) != null) {
verifier = ring;
break;
}
}
PGPSignature signature = metadata.getVerifiedSignatures().get(fingerprint);
sb.append(df.format(signature.getCreationTime())).append(' ')
.append(fingerprint).append(' ')
.append(new OpenPgpV4Fingerprint(verifier)).append('\n');
}
try {
verifyOut.createNewFile();
PrintStream verifyPrinter = new PrintStream(new FileOutputStream(verifyOut));
// CHECKSTYLE:OFF
verifyPrinter.println(sb.toString());
// CHECKSTYLE:ON
verifyPrinter.close();
} catch (IOException e) {
if (verifyWith != null) {
for (OpenPgpV4Fingerprint fingerprint : metadata.getVerifiedSignatures().keySet()) {
PGPPublicKeyRing verifier = null;
for (PGPPublicKeyRing ring : verifyWith) {
if (ring.getPublicKey(fingerprint.getKeyId()) != null) {
verifier = ring;
break;
}
}
PGPSignature signature = metadata.getVerifiedSignatures().get(fingerprint);
sb.append(df.format(signature.getCreationTime())).append(' ')
.append(fingerprint).append(' ')
.append(new OpenPgpV4Fingerprint(verifier)).append('\n');
}
try {
verifyOut.createNewFile();
PrintStream verifyPrinter = new PrintStream(new FileOutputStream(verifyOut));
// CHECKSTYLE:OFF
verifyPrinter.println(sb.toString());
// CHECKSTYLE:ON
verifyPrinter.close();
} catch (IOException e) {
err_ln("Error writing verifications file: " + e);
}
}
}
}

View file

@ -16,14 +16,12 @@
package org.pgpainless.sop.commands;
import static org.pgpainless.sop.Print.err_ln;
import static org.pgpainless.sop.Print.print_ln;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import javax.annotation.Nullable;
import java.util.List;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
@ -35,9 +33,8 @@ 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.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider;
import org.pgpainless.sop.SopKeyUtil;
import org.pgpainless.util.Passphrase;
import picocli.CommandLine;
@ -87,38 +84,27 @@ public class Encrypt implements Runnable {
EncryptionOptions encOpt = new EncryptionOptions();
SigningOptions signOpt = new SigningOptions();
for (int i = 0 ; i < certs.length; i++) {
try (InputStream fileIn = new FileInputStream(certs[i])) {
PGPPublicKeyRing publicKey = PGPainless.readKeyRing().publicKeyRing(fileIn);
encOpt.addRecipient(publicKey);
} catch (IOException e) {
err_ln("Cannot read certificate " + certs[i].getName());
err_ln(e.getMessage());
System.exit(1);
try {
List<PGPPublicKeyRing> encryptionKeys = SopKeyUtil.loadCertificatesFromFile(certs);
for (PGPPublicKeyRing key : encryptionKeys) {
encOpt.addRecipient(key);
}
} catch (IOException e) {
err_ln(e.getMessage());
System.exit(1);
return;
}
for (int i = 0; i < withPassword.length; i++) {
Passphrase passphrase = Passphrase.fromPassword(withPassword[i]);
for (String s : withPassword) {
Passphrase passphrase = Passphrase.fromPassword(s);
encOpt.addPassphrase(passphrase);
}
final Scanner scanner = new Scanner(System.in);
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
for (int i = 0; i < signWith.length; i++) {
try (FileInputStream fileIn = new FileInputStream(signWith[i])) {
PGPSecretKeyRing secretKey = PGPainless.readKeyRing().secretKeyRing(fileIn);
SecretKeyRingProtector protector = SecretKeyRingProtector.defaultSecretKeyRingProtector(
new SecretKeyPassphraseProvider() {
@Nullable
@Override
public Passphrase getPassphraseFor(Long keyId) {
print_ln("Please provide the passphrase for key " + new OpenPgpV4Fingerprint(secretKey));
String password = scanner.nextLine();
Passphrase passphrase = Passphrase.fromPassword(password.trim());
return passphrase;
}
}
);
signOpt.addInlineSignature(protector, secretKey,
type == Type.text || type == Type.mime ?
DocumentSignatureType.CANONICAL_TEXT_DOCUMENT : DocumentSignatureType.BINARY_DOCUMENT);

View file

@ -21,15 +21,12 @@ import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.encryption_signing.EncryptionBuilderInterface;
import org.pgpainless.encryption_signing.EncryptionOptions;
import org.pgpainless.encryption_signing.EncryptionResult;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.encryption_signing.SigningOptions;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.sop.Print;
import picocli.CommandLine;

View file

@ -103,7 +103,8 @@ public class EncryptDecryptTest {
FileInputStream msgAscIn = new FileInputStream(msgAscFile);
System.setIn(msgAscIn);
ByteArrayOutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
PrintStream pOut = new PrintStream(out);
System.setOut(pOut);
new CommandLine(new PGPainlessCLI()).execute("decrypt",
"--verify-out", verifyFile.getAbsolutePath(),
"--verify-with", romeoCertFile.getAbsolutePath(),