1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-12-10 06:11:08 +01:00

Rearrange armored input stream workaround code

This commit is contained in:
Paul Schaub 2021-08-08 15:58:12 +02:00
parent 1983cfb4ac
commit 944d79b009
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 87 additions and 41 deletions

View file

@ -15,7 +15,6 @@
*/
package org.pgpainless.key.parsing;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@ -25,7 +24,6 @@ import java.util.Iterator;
import java.util.List;
import javax.annotation.Nonnull;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPMarker;
import org.bouncycastle.openpgp.PGPObjectFactory;
@ -33,12 +31,10 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.collection.PGPKeyRingCollection;
import org.pgpainless.util.ArmoredInputStreamFactory;
import org.pgpainless.util.ArmorUtils;
public class KeyRingReader {
@ -109,7 +105,7 @@ public class KeyRingReader {
public static PGPPublicKeyRing readPublicKeyRing(@Nonnull InputStream inputStream) throws IOException {
PGPObjectFactory objectFactory = new PGPObjectFactory(
getDecoderStream(inputStream),
ArmorUtils.getDecoderStream(inputStream),
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
Object next;
do {
@ -131,7 +127,7 @@ public class KeyRingReader {
public static PGPPublicKeyRingCollection readPublicKeyRingCollection(@Nonnull InputStream inputStream)
throws IOException, PGPException {
PGPObjectFactory objectFactory = new PGPObjectFactory(
getDecoderStream(inputStream),
ArmorUtils.getDecoderStream(inputStream),
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
List<PGPPublicKeyRing> rings = new ArrayList<>();
@ -161,7 +157,7 @@ public class KeyRingReader {
}
public static PGPSecretKeyRing readSecretKeyRing(@Nonnull InputStream inputStream) throws IOException {
InputStream decoderStream = getDecoderStream(inputStream);
InputStream decoderStream = ArmorUtils.getDecoderStream(inputStream);
PGPObjectFactory objectFactory = new PGPObjectFactory(
decoderStream,
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
@ -187,7 +183,7 @@ public class KeyRingReader {
public static PGPSecretKeyRingCollection readSecretKeyRingCollection(@Nonnull InputStream inputStream)
throws IOException, PGPException {
PGPObjectFactory objectFactory = new PGPObjectFactory(
getDecoderStream(inputStream),
ArmorUtils.getDecoderStream(inputStream),
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
List<PGPSecretKeyRing> rings = new ArrayList<>();
@ -220,34 +216,4 @@ public class KeyRingReader {
throws IOException, PGPException {
return new PGPKeyRingCollection(inputStream, isSilent);
}
/**
* Hacky workaround for #96.
* For {@link PGPPublicKeyRingCollection#PGPPublicKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
* or {@link PGPSecretKeyRingCollection#PGPSecretKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
* to read all PGPKeyRings properly, we apparently have to make sure that the {@link InputStream} that is given
* as constructor argument is a {@link PGPUtil.BufferedInputStreamExt}.
* Since {@link PGPUtil#getDecoderStream(InputStream)} will return an {@link org.bouncycastle.bcpg.ArmoredInputStream}
* if the underlying input stream contains armored data, we have to nest two method calls to make sure that the
* end-result is a {@link PGPUtil.BufferedInputStreamExt}.
*
* This is a hacky solution.
*
* @param inputStream input stream
* @return BufferedInputStreamExt
*/
private static InputStream getDecoderStream(InputStream inputStream) throws IOException {
InputStream decoderStream = PGPUtil.getDecoderStream(inputStream);
// Data is not armored -> return
if (decoderStream instanceof BufferedInputStream) {
return decoderStream;
}
// Wrap armored input stream with fix for #159
if (decoderStream instanceof ArmoredInputStream) {
decoderStream = ArmoredInputStreamFactory.get(decoderStream);
}
decoderStream = PGPUtil.getDecoderStream(decoderStream);
return decoderStream;
}
}

View file

@ -36,7 +36,6 @@ import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
import org.bouncycastle.util.encoders.Hex;
import org.pgpainless.PGPainless;
@ -48,6 +47,7 @@ import org.pgpainless.key.util.OpenPgpKeyAttributeUtil;
import org.pgpainless.key.util.RevocationAttributes;
import org.pgpainless.policy.Policy;
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
import org.pgpainless.util.ArmorUtils;
/**
* Utility methods related to signatures.
@ -196,7 +196,7 @@ public class SignatureUtils {
public static List<PGPSignature> readSignatures(InputStream inputStream) throws IOException, PGPException {
List<PGPSignature> signatures = new ArrayList<>();
InputStream pgpIn = PGPUtil.getDecoderStream(inputStream);
InputStream pgpIn = ArmorUtils.getDecoderStream(inputStream);
PGPObjectFactory objectFactory = new PGPObjectFactory(
pgpIn, ImplementationFactory.getInstance().getKeyFingerprintCalculator());

View file

@ -15,6 +15,7 @@
*/
package org.pgpainless.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -32,6 +33,8 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.key.OpenPgpV4Fingerprint;
@ -204,4 +207,32 @@ public class ArmorUtils {
}
return values;
}
/**
* Hacky workaround for #96.
* For {@link PGPPublicKeyRingCollection#PGPPublicKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
* or {@link PGPSecretKeyRingCollection#PGPSecretKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
* to read all PGPKeyRings properly, we apparently have to make sure that the {@link InputStream} that is given
* as constructor argument is a {@link PGPUtil.BufferedInputStreamExt}.
* Since {@link PGPUtil#getDecoderStream(InputStream)} will return an {@link org.bouncycastle.bcpg.ArmoredInputStream}
* if the underlying input stream contains armored data, we have to nest two method calls to make sure that the
* end-result is a {@link PGPUtil.BufferedInputStreamExt}.
*
* This is a hacky solution.
*
* @param inputStream input stream
* @return BufferedInputStreamExt
*/
public static InputStream getDecoderStream(InputStream inputStream) throws IOException {
InputStream decoderStream = PGPUtil.getDecoderStream(inputStream);
// Data is not armored -> return
if (decoderStream instanceof BufferedInputStream) {
return decoderStream;
}
// Wrap armored input stream with fix for #159
decoderStream = CRCingArmoredInputStreamWrapper.possiblyWrap(decoderStream);
decoderStream = PGPUtil.getDecoderStream(decoderStream);
return decoderStream;
}
}