mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-01-08 19:27:57 +01:00
Fix SOP encrypt-decrypt test
This commit is contained in:
parent
b0692b4dc5
commit
3cd64b61ca
8 changed files with 88 additions and 72 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in a new issue