mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-05 03:55:58 +01:00
Implement stream dump
This commit is contained in:
parent
5b9e72d42c
commit
5c25b0c730
2 changed files with 481 additions and 0 deletions
|
@ -0,0 +1,424 @@
|
|||
package org.pgpainless.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bouncycastle.bcpg.SignatureSubpacket;
|
||||
import org.bouncycastle.bcpg.sig.EmbeddedSignature;
|
||||
import org.bouncycastle.bcpg.sig.Exportable;
|
||||
import org.bouncycastle.bcpg.sig.Features;
|
||||
import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint;
|
||||
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
||||
import org.bouncycastle.bcpg.sig.IssuerKeyID;
|
||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||
import org.bouncycastle.bcpg.sig.NotationData;
|
||||
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
||||
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
||||
import org.bouncycastle.bcpg.sig.Revocable;
|
||||
import org.bouncycastle.bcpg.sig.RevocationKey;
|
||||
import org.bouncycastle.bcpg.sig.RevocationReason;
|
||||
import org.bouncycastle.bcpg.sig.SignatureCreationTime;
|
||||
import org.bouncycastle.bcpg.sig.SignatureExpirationTime;
|
||||
import org.bouncycastle.bcpg.sig.SignatureTarget;
|
||||
import org.bouncycastle.bcpg.sig.SignerUserID;
|
||||
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||
import org.bouncycastle.openpgp.PGPCompressedData;
|
||||
import org.bouncycastle.openpgp.PGPEncryptedData;
|
||||
import org.bouncycastle.openpgp.PGPEncryptedDataList;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPLiteralData;
|
||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
||||
import org.bouncycastle.openpgp.PGPOnePassSignatureList;
|
||||
import org.bouncycastle.openpgp.PGPPBEEncryptedData;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
|
||||
import org.bouncycastle.openpgp.PGPSessionKey;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory;
|
||||
import org.bouncycastle.openpgp.operator.bc.BcSessionKeyDataDecryptorFactory;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||
import org.pgpainless.algorithm.Feature;
|
||||
import org.pgpainless.algorithm.HashAlgorithm;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||
import org.pgpainless.algorithm.SignatureType;
|
||||
import org.pgpainless.algorithm.StreamEncoding;
|
||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||
import org.pgpainless.key.util.RevocationAttributes;
|
||||
|
||||
public class StreamDumper {
|
||||
|
||||
public static void dump(InputStream inputStream, PGPSessionKey sessionKey) throws IOException, PGPException {
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
StringBuilderWrapper sbw = new StringBuilderWrapper(stringBuilder);
|
||||
|
||||
PGPObjectFactory objectFactory = new BcPGPObjectFactory(inputStream);
|
||||
walkObjects(sbw, objectFactory, sessionKey);
|
||||
|
||||
System.out.println(sbw);
|
||||
}
|
||||
|
||||
private static void walkObjects(StringBuilderWrapper sbw, PGPObjectFactory objectFactory, PGPSessionKey sessionKey) throws IOException, PGPException {
|
||||
Object next;
|
||||
|
||||
while ((next = objectFactory.nextObject()) != null) {
|
||||
|
||||
if (next instanceof PGPOnePassSignatureList) {
|
||||
PGPOnePassSignatureList onePassSignatures = (PGPOnePassSignatureList) next;
|
||||
Iterator<PGPOnePassSignature> iterator = onePassSignatures.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
PGPOnePassSignature pgpOnePassSignature = iterator.next();
|
||||
sbw.appendLine("One-Pass Signature Packet").iind()
|
||||
.appendLine("Type: " + SignatureType.valueOf(pgpOnePassSignature.getSignatureType()))
|
||||
.appendLine("Public Key Algorithm: " + PublicKeyAlgorithm.fromId(pgpOnePassSignature.getKeyAlgorithm()))
|
||||
.appendLine("Hash Algorithm: " + HashAlgorithm.fromId(pgpOnePassSignature.getHashAlgorithm()))
|
||||
.appendLine("Issuer Key ID: " + Long.toHexString(pgpOnePassSignature.getKeyID()))
|
||||
.dind()
|
||||
.emptyLine();
|
||||
}
|
||||
}
|
||||
else if (next instanceof PGPSignatureList) {
|
||||
PGPSignatureList signatures = (PGPSignatureList) next;
|
||||
for (PGPSignature signature : signatures) {
|
||||
appendSignature(sbw, signature);
|
||||
sbw.emptyLine();
|
||||
}
|
||||
}
|
||||
else if (next instanceof PGPEncryptedDataList) {
|
||||
PGPEncryptedDataList encryptedDataList = (PGPEncryptedDataList) next;
|
||||
SessionKeyDataDecryptorFactory sessionKeyDataDecryptorFactory = null;
|
||||
if (sessionKey != null) {
|
||||
sessionKeyDataDecryptorFactory = new BcSessionKeyDataDecryptorFactory(sessionKey);
|
||||
}
|
||||
for (PGPEncryptedData encryptedData : encryptedDataList) {
|
||||
if (encryptedData instanceof PGPPublicKeyEncryptedData) {
|
||||
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) encryptedData;
|
||||
sbw.appendLine("Public-Key Encrypted Session Key Packet").iind()
|
||||
.appendLine("Recipient: " + Long.toHexString(pkesk.getKeyID()));
|
||||
|
||||
if (sessionKeyDataDecryptorFactory != null) {
|
||||
try {
|
||||
InputStream inputStream = pkesk.getDataStream(sessionKeyDataDecryptorFactory);
|
||||
sbw.appendLine("Session Key: " + Hex.toHexString(sessionKey.getKey()));
|
||||
sbw.appendLine("Symmetric Algorithm: " + SymmetricKeyAlgorithm.fromId(sessionKey.getAlgorithm()));
|
||||
sbw.appendLine("Decryption Successful");
|
||||
sbw.emptyLine();
|
||||
|
||||
PGPObjectFactory decryptedFactory = new BcPGPObjectFactory(inputStream);
|
||||
walkObjects(sbw, decryptedFactory, sessionKey);
|
||||
} catch (PGPException e) {
|
||||
sbw.appendLine("Decryption Failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (pkesk.isIntegrityProtected()) {
|
||||
sbw.appendLine("Modification Detection Code Packet").iind()
|
||||
.appendLine("Valid: " + pkesk.verify())
|
||||
.dind();
|
||||
}
|
||||
} else if (encryptedData instanceof PGPPBEEncryptedData) {
|
||||
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) encryptedData;
|
||||
sbw.appendLine("Symmetric-Key Encrypted Session Key Packet").iind()
|
||||
.appendLine("Integrity Protected: " + skesk.isIntegrityProtected())
|
||||
.dind().emptyLine();
|
||||
}
|
||||
}
|
||||
sbw.emptyLine();
|
||||
}
|
||||
else if (next instanceof PGPLiteralData) {
|
||||
PGPLiteralData literalData = (PGPLiteralData) next;
|
||||
StreamEncoding encoding = StreamEncoding.fromCode(literalData.getFormat());
|
||||
String fileName = literalData.getFileName();
|
||||
Date modificationDate = literalData.getModificationTime();
|
||||
|
||||
sbw.appendLine("Literal Data Packet").iind()
|
||||
.appendLine("Format: " + encoding);
|
||||
if (fileName != null && !fileName.isEmpty()) {
|
||||
sbw.appendLine("File Name: " + fileName);
|
||||
}
|
||||
if (modificationDate != null && modificationDate.getTime() != 0) {
|
||||
sbw.appendLine("Modification Date: " + DateUtil.formatUTCDate(modificationDate));
|
||||
}
|
||||
|
||||
byte[] peek = new byte[512];
|
||||
InputStream literalIn = literalData.getDataStream();
|
||||
int read = literalIn.read(peek);
|
||||
Streams.drain(literalIn);
|
||||
literalIn.close();
|
||||
|
||||
String content = "";
|
||||
if (read != -1) {
|
||||
content = new String(peek, 0, read).replace("\r", "\\r").replace("\n", "\\n");
|
||||
}
|
||||
sbw.appendLine("Content: \"" + content + "\"")
|
||||
.dind()
|
||||
.emptyLine();
|
||||
}
|
||||
else if (next instanceof PGPCompressedData) {
|
||||
PGPCompressedData compressedData = (PGPCompressedData) next;
|
||||
sbw.appendLine("Compressed Data Packet").iind()
|
||||
.appendLine("Algorithm: " + CompressionAlgorithm.fromId(compressedData.getAlgorithm()))
|
||||
.emptyLine();
|
||||
|
||||
PGPObjectFactory compressedFactory = new BcPGPObjectFactory(compressedData.getDataStream());
|
||||
walkObjects(sbw, compressedFactory, sessionKey);
|
||||
sbw.dind();
|
||||
}
|
||||
/*
|
||||
|
||||
case PacketTags.SYMMETRIC_KEY_ENC_SESSION:
|
||||
case PacketTags.ONE_PASS_SIGNATURE:
|
||||
case PacketTags.SECRET_KEY:
|
||||
case PacketTags.PUBLIC_KEY:
|
||||
case PacketTags.SECRET_SUBKEY:
|
||||
case PacketTags.COMPRESSED_DATA:
|
||||
case PacketTags.SYMMETRIC_KEY_ENC:
|
||||
case PacketTags.MARKER:
|
||||
case PacketTags.LITERAL_DATA:
|
||||
case PacketTags.TRUST:
|
||||
case PacketTags.USER_ID:
|
||||
case PacketTags.PUBLIC_SUBKEY:
|
||||
case PacketTags.USER_ATTRIBUTE:
|
||||
case PacketTags.SYM_ENC_INTEGRITY_PRO:
|
||||
case PacketTags.MOD_DETECTION_CODE:
|
||||
|
||||
case PacketTags.EXPERIMENTAL_1:
|
||||
case PacketTags.EXPERIMENTAL_2:
|
||||
case PacketTags.EXPERIMENTAL_3:
|
||||
case PacketTags.EXPERIMENTAL_4:
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendSignature(StringBuilderWrapper sbw, PGPSignature signature) throws PGPException {
|
||||
sbw.appendLine("Signature Packet").iind()
|
||||
.appendLine("Version: " + signature.getVersion())
|
||||
.appendLine("Type: " + SignatureType.valueOf(signature.getSignatureType()))
|
||||
.appendLine("Public Key Algorithm: " + PublicKeyAlgorithm.fromId(signature.getKeyAlgorithm()))
|
||||
.appendLine("Hash Algorithm: " + HashAlgorithm.fromId(signature.getHashAlgorithm()));
|
||||
|
||||
if (signature.getHashedSubPackets().toArray().length != 0) {
|
||||
sbw.appendLine("Hashed Area:").iind();
|
||||
appendSubpacketVector(sbw, signature.getHashedSubPackets());
|
||||
sbw.dind();
|
||||
}
|
||||
|
||||
if (signature.getUnhashedSubPackets().toArray().length != 0) {
|
||||
sbw.appendLine("Unhashed Area:").iind();
|
||||
appendSubpacketVector(sbw, signature.getUnhashedSubPackets());
|
||||
sbw.dind();
|
||||
}
|
||||
|
||||
sbw.appendLine("Digest Prefix: " + Hex.toHexString(signature.getDigestPrefix()))
|
||||
.appendLine("Signature: ").iind()
|
||||
.appendLine(Hex.toHexString(signature.getSignature())).dind()
|
||||
.dind();
|
||||
}
|
||||
|
||||
private static void appendSubpacketVector(StringBuilderWrapper sbw, PGPSignatureSubpacketVector vector) throws PGPException {
|
||||
PGPSignatureList embeddedSignatures = vector.getEmbeddedSignatures();
|
||||
int embeddedSigCount = 0;
|
||||
|
||||
for (SignatureSubpacket subpacket : vector.toArray()) {
|
||||
switch (org.pgpainless.algorithm.SignatureSubpacket.fromCode(subpacket.getType())) {
|
||||
case signatureCreationTime:
|
||||
SignatureCreationTime signatureCreationTime = (SignatureCreationTime) subpacket;
|
||||
sbw.appendLine("Signature Creation Time: " + DateUtil.formatUTCDate(signatureCreationTime.getTime()) + (signatureCreationTime.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case signatureExpirationTime:
|
||||
SignatureExpirationTime signatureExpirationTime = (SignatureExpirationTime) subpacket;
|
||||
sbw.appendLine("Signature Expiration Time: " + signatureExpirationTime.getTime() + (signatureExpirationTime.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case exportableCertification:
|
||||
Exportable exportable = (Exportable) subpacket;
|
||||
sbw.appendLine("Exportable: " + exportable.isExportable() + (exportable.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case trustSignature:
|
||||
TrustSignature trustSignature = (TrustSignature) subpacket;
|
||||
sbw.appendLine("Trust Signature" + (trustSignature.isCritical() ? " (critical)" : "") + ":").iind()
|
||||
.appendLine("Depth: " + trustSignature.getDepth())
|
||||
.appendLine("Amount: " + trustSignature.getTrustAmount())
|
||||
.dind();
|
||||
break;
|
||||
case regularExpression:
|
||||
sbw.appendLine("Regular Expression: " + new String(subpacket.getData()));
|
||||
break;
|
||||
case revocable:
|
||||
Revocable revocable = (Revocable) subpacket;
|
||||
sbw.appendLine("Revocable: " + revocable.isRevocable() + (revocable.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case keyExpirationTime:
|
||||
KeyExpirationTime keyExpirationTime = (KeyExpirationTime) subpacket;
|
||||
sbw.appendLine("Key Expiration Time: " + keyExpirationTime.getTime() + (keyExpirationTime.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case placeholder:
|
||||
sbw.appendLine("Placeholder: " + new String(subpacket.getData()));
|
||||
break;
|
||||
case preferredSymmetricAlgorithms:
|
||||
PreferredAlgorithms preferredSymmetricAlgorithms = (PreferredAlgorithms) subpacket;
|
||||
int[] symAlgIds = preferredSymmetricAlgorithms.getPreferences();
|
||||
SymmetricKeyAlgorithm[] symAlgs = new SymmetricKeyAlgorithm[symAlgIds.length];
|
||||
for (int i = 0; i < symAlgs.length; i++) {
|
||||
symAlgs[i] = SymmetricKeyAlgorithm.fromId(symAlgIds[i]);
|
||||
}
|
||||
sbw.appendLine("Preferred Symmetric Algorithms: " + Arrays.toString(symAlgs) + (preferredSymmetricAlgorithms.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case revocationKey:
|
||||
RevocationKey revocationKey = (RevocationKey) subpacket;
|
||||
sbw.appendLine("Revocation Key" + (revocationKey.isCritical() ? " (critical)" : "") + ":").iind()
|
||||
.appendLine("Key Algorithm: " + PublicKeyAlgorithm.fromId(revocationKey.getAlgorithm()))
|
||||
.appendLine("Signature Class: " + revocationKey.getSignatureClass())
|
||||
.appendLine("Fingerprint: " + new String(revocationKey.getFingerprint()))
|
||||
.dind();
|
||||
break;
|
||||
case issuerKeyId:
|
||||
IssuerKeyID issuerKeyID = (IssuerKeyID) subpacket;
|
||||
sbw.appendLine("Issuer Key ID: " + Long.toHexString(issuerKeyID.getKeyID()) + (issuerKeyID.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case notationData:
|
||||
NotationData notationData = (NotationData) subpacket;
|
||||
sbw.appendLine("Notation Data" + (notationData.isCritical() ? " (critical)" : "") + ":").iind()
|
||||
.appendLine("Notation Name: " + notationData.getNotationName())
|
||||
.appendLine("Notation Value: " + notationData.getNotationValue())
|
||||
.dind();
|
||||
break;
|
||||
case preferredHashAlgorithms:
|
||||
PreferredAlgorithms preferredHashAlgorithms = (PreferredAlgorithms) subpacket;
|
||||
int[] hashAlgIds = preferredHashAlgorithms.getPreferences();
|
||||
HashAlgorithm[] hashAlgs = new HashAlgorithm[hashAlgIds.length];
|
||||
for (int i = 0; i < hashAlgs.length; i++) {
|
||||
hashAlgs[i] = HashAlgorithm.fromId(hashAlgIds[i]);
|
||||
}
|
||||
sbw.appendLine("Preferred Hash Algorithms: " + Arrays.toString(hashAlgs) + (preferredHashAlgorithms.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case preferredCompressionAlgorithms:
|
||||
PreferredAlgorithms preferredCompressionAlgorithms = (PreferredAlgorithms) subpacket;
|
||||
int[] compAlgIds = preferredCompressionAlgorithms.getPreferences();
|
||||
CompressionAlgorithm[] compAlgs = new CompressionAlgorithm[compAlgIds.length];
|
||||
for (int i = 0; i < compAlgs.length; i++) {
|
||||
compAlgs[i] = CompressionAlgorithm.fromId(compAlgIds[i]);
|
||||
}
|
||||
sbw.appendLine("Preferred Compression Algorithms: " + Arrays.toString(compAlgs) + (preferredCompressionAlgorithms.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case keyServerPreferences:
|
||||
sbw.appendLine("Key Server Preferences: " + new String(subpacket.getData()));
|
||||
break;
|
||||
case preferredKeyServers:
|
||||
sbw.appendLine("Preferred Key Servers: " + new String(subpacket.getData()));
|
||||
break;
|
||||
case primaryUserId:
|
||||
PrimaryUserID primaryUserID = (PrimaryUserID) subpacket;
|
||||
sbw.appendLine("Primary User-ID: " + primaryUserID.isPrimaryUserID() + (primaryUserID.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case policyUrl:
|
||||
sbw.appendLine("Policy-URL: " + new String(subpacket.getData()));
|
||||
break;
|
||||
case keyFlags:
|
||||
KeyFlags keyFlags = (KeyFlags) subpacket;
|
||||
KeyFlag[] flags = KeyFlag.fromBitmask(keyFlags.getFlags()).toArray(new KeyFlag[0]);
|
||||
sbw.appendLine("Key Flags: " + Arrays.toString(flags) + (keyFlags.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case signerUserId:
|
||||
SignerUserID signerUserID = (SignerUserID) subpacket;
|
||||
sbw.appendLine("Signer User-ID: " + signerUserID.getID() + (signerUserID.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case revocationReason:
|
||||
RevocationReason revocationReason = (RevocationReason) subpacket;
|
||||
sbw.appendLine("Revocation Reason: " + RevocationAttributes.Reason.fromCode(revocationReason.getRevocationReason()) + (revocationReason.isCritical() ? " (critical)" : "")).iind()
|
||||
.appendLine("Description: " + revocationReason.getRevocationDescription()).dind();
|
||||
break;
|
||||
case features:
|
||||
Features features = (Features) subpacket;
|
||||
Feature[] featurez = Feature.fromBitmask(features.getFeatures()).toArray(new Feature[0]);
|
||||
sbw.appendLine("Features: " + Arrays.toString(featurez) + (features.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case signatureTarget:
|
||||
SignatureTarget signatureTarget = (SignatureTarget) subpacket;
|
||||
sbw.appendLine("Signature Target" + (signatureTarget.isCritical() ? " (critical)" : "" + ":")).iind()
|
||||
.appendLine("Public Key Algorithm: " + PublicKeyAlgorithm.fromId(signatureTarget.getPublicKeyAlgorithm()))
|
||||
.appendLine("Hash Algorithm: " + HashAlgorithm.fromId(signatureTarget.getHashAlgorithm()))
|
||||
.appendLine("Hash Data: " + Hex.toHexString(signatureTarget.getHashData()))
|
||||
.dind();
|
||||
break;
|
||||
case embeddedSignature:
|
||||
EmbeddedSignature embeddedSignature = (EmbeddedSignature) subpacket;
|
||||
sbw.appendLine("Embedded Signature" + (embeddedSignature.isCritical() ? " (critical)" : "") + ":").iind();
|
||||
appendSignature(sbw, embeddedSignatures.get(embeddedSigCount++));
|
||||
break;
|
||||
case issuerFingerprint:
|
||||
IssuerFingerprint issuerFingerprint = (IssuerFingerprint) subpacket;
|
||||
sbw.appendLine("Issuer Fingerprint: " + Hex.toHexString(issuerFingerprint.getFingerprint()) + (issuerFingerprint.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case preferredAEADAlgorithms:
|
||||
PreferredAlgorithms preferredAEADAlgorithms = (PreferredAlgorithms) subpacket;
|
||||
int[] aeadAlgIds = preferredAEADAlgorithms.getPreferences();
|
||||
sbw.appendLine("Preferred AEAD Algorithms: " + Arrays.toString(aeadAlgIds) + (preferredAEADAlgorithms.isCritical() ? " (critical)" : ""));
|
||||
break;
|
||||
case intendedRecipientFingerprint:
|
||||
IntendedRecipientFingerprint intendedRecipientFingerprint = (IntendedRecipientFingerprint) subpacket;
|
||||
sbw.appendLine("Intended Recipient Fingerprint" + (intendedRecipientFingerprint.isCritical() ? " critical" : "") + ":").iind()
|
||||
.appendLine("Key Version: " + intendedRecipientFingerprint.getKeyVersion())
|
||||
.appendLine("Fingerprint: " + Hex.toHexString(intendedRecipientFingerprint.getFingerprint()))
|
||||
.dind();
|
||||
break;
|
||||
case attestedCertification:
|
||||
sbw.appendLine("Attested Certification: " + new String(subpacket.getData()));
|
||||
break;
|
||||
default:
|
||||
sbw.appendLine("Experimental Subpacket (Tag " + subpacket.getType() + ")" + (subpacket.isCritical() ? " (critical)" : "") + ":" + new String(subpacket.getData()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringBuilderWrapper {
|
||||
private final StringBuilder sb;
|
||||
private int indentationLevel = 0;
|
||||
private final int spacesPerLevel = 2;
|
||||
|
||||
public StringBuilderWrapper(StringBuilder sb) {
|
||||
this.sb = sb;
|
||||
}
|
||||
|
||||
public StringBuilderWrapper appendLine(String line) {
|
||||
spaces();
|
||||
sb.append(line).append('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringBuilderWrapper iind() {
|
||||
indentationLevel++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringBuilderWrapper dind() {
|
||||
indentationLevel--;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringBuilderWrapper emptyLine() {
|
||||
sb.append('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
private StringBuilderWrapper spaces() {
|
||||
for (int i = 0; i < indentationLevel * spacesPerLevel; i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.pgpainless.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredInputStream;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPSessionKey;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||
|
||||
public class StreamDumpTest {
|
||||
|
||||
@Test
|
||||
public void test() throws IOException, PGPException {
|
||||
String encryptedMessage = "-----BEGIN PGP MESSAGE-----\n" +
|
||||
"\n" +
|
||||
"wV4Di9iOlMDSAzMSAQdAu/2VmD0uZASFHqAD0IVNq7C8rdsJ+ZQd2nQsuBilygUw\n" +
|
||||
"9bK+bOzU6ksTZgKgdAjO8zpvM+N0B3L0TtiwLr5rj0rPkCyVLdACnBpWOCZCMpsK\n" +
|
||||
"0j4B4um24+oCDHtxRu1e1IvsboBtGN9ElxidGAiUdPJ3L0QrNVgzdmVTwuywtIHW\n" +
|
||||
"r66Eaq8vCTmJpcsy0BYTiQ==\n" +
|
||||
"=FY/Q\n" +
|
||||
"-----END PGP MESSAGE-----\n";
|
||||
PGPSessionKey sessionKey = new PGPSessionKey(SymmetricKeyAlgorithm.AES_256.getAlgorithmId(), Hex.decode("920B1779565C8DF4DD9DB46966CDF2B51BC882C241DE8EF437CADEC711E7EB04"));
|
||||
|
||||
String signedMessage = "-----BEGIN PGP MESSAGE-----\n" +
|
||||
"\n" +
|
||||
"xA0DAAgB0D9vhlIm/osBxA0DAAoWCTXiD9yZ2YYByxRiAAAAAABIZWxsbywgd29y\n" +
|
||||
"bGQhCsJ1BAAWCgAnBYJcdpUyFiEEjeZMrRdY/BlFYM9ZCTXiD9yZ2YYJEAk14g/c\n" +
|
||||
"mdmGAAC5AgD/U/FD8PPqqABrkdg9bV4aToP6YENgXGq8M7SIvTaznl0BAM1KdOKs\n" +
|
||||
"UWPQgh5AJp3kOUzSO7v+brfw03O1wQaOmgsHwsBzBAABCAAnBYJdkKU/FiEEPoh3\n" +
|
||||
"yHcnRpKXUYn10D9vhlIm/osJENA/b4ZSJv6LAAAQ1Qf/bC4uL61DQrR0s+3n7By8\n" +
|
||||
"Rp0cfppfR94NK9GUtCcL03Ci78qimpjcZja+r03xTj4r3TGASRngaYD0cOU+erF9\n" +
|
||||
"DO3PPGZKxajOqtFXoQKdQnUhaRnU2CMfL+voRzH7kFssvcHzy7JoeFDLxadt8yym\n" +
|
||||
"Hm3vN+oDB3b8uWVEzaVMn71cbjJzlsLBaLclSlE/Nj36x9TeunnHhZJ7BFmkTaBd\n" +
|
||||
"W5kdBtqIV6Mii+xiYjrtrkFzYkEDNz6hK2so8SjpaGck2tSiBSrybf0/CLWwb/+e\n" +
|
||||
"i6yLPi6Afbxz+5Yp4jjxNkUdjeQFNFExix0DUPVowhZQN9hwZvJXmfUzi71+BB6N\n" +
|
||||
"uA==\n" +
|
||||
"=BDwS\n" +
|
||||
"-----END PGP MESSAGE-----\n";
|
||||
|
||||
String compressedSignedMessage = "-----BEGIN PGP MESSAGE-----\n" +
|
||||
"\n" +
|
||||
"owGbwMvMwCH2sPOSUOzzWymMp0WSGGK6InU9UnNy8nUUyvOLclIUuTpKWRjEOBhk\n" +
|
||||
"xRRZ8jZHv1c9Zfp0SurkSJguViaQFgYuTgGYSJ09w/8M9xn6J9em8Bvs3rHgYd+G\n" +
|
||||
"z519Zy++FFuYsPHwz8KmXNliRoaNP2zq+A5kp7MJWjc2JrdXW8y+GTd9So2lDcMq\n" +
|
||||
"h3UsTFwA\n" +
|
||||
"=56Gw\n" +
|
||||
"-----END PGP MESSAGE-----";
|
||||
|
||||
ArmoredInputStream inputStream = new ArmoredInputStream(new ByteArrayInputStream(encryptedMessage.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
StreamDumper.dump(inputStream, sessionKey);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue