org.spongycastle.openpgp.PGPEncryptedData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pg Show documentation
Show all versions of pg Show documentation
Spongy Castle is a package-rename (org.bouncycastle.* to org.spongycastle.*) of Bouncy Castle
intended for the Android platform. Android unfortunately ships with a stripped-down version of
Bouncy Castle, which prevents easy upgrades - Spongy Castle overcomes this and provides a full,
up-to-date version of the Bouncy Castle cryptographic libs.
The newest version!
package org.spongycastle.openpgp;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.spongycastle.bcpg.InputStreamPacket;
import org.spongycastle.bcpg.SymmetricEncIntegrityPacket;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.spongycastle.openpgp.operator.PGPDataDecryptor;
import org.spongycastle.openpgp.operator.PGPDataDecryptorFactory;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
import org.spongycastle.util.Arrays;
/**
* A PGP encrypted data object.
*
* Encrypted data packets are decrypted using a {@link PGPDataDecryptor} obtained from a
* {@link PGPDataDecryptorFactory}.
*
*/
public abstract class PGPEncryptedData
implements SymmetricKeyAlgorithmTags
{
protected class TruncatedStream extends InputStream
{
int[] lookAhead = new int[22];
int bufPtr;
InputStream in;
TruncatedStream(
InputStream in)
throws IOException
{
for (int i = 0; i != lookAhead.length; i++)
{
if ((lookAhead[i] = in.read()) < 0)
{
throw new EOFException();
}
}
bufPtr = 0;
this.in = in;
}
public int read()
throws IOException
{
int ch = in.read();
if (ch >= 0)
{
int c = lookAhead[bufPtr];
lookAhead[bufPtr] = ch;
bufPtr = (bufPtr + 1) % lookAhead.length;
return c;
}
return -1;
}
int[] getLookAhead()
{
int[] tmp = new int[lookAhead.length];
int count = 0;
for (int i = bufPtr; i != lookAhead.length; i++)
{
tmp[count++] = lookAhead[i];
}
for (int i = 0; i != bufPtr; i++)
{
tmp[count++] = lookAhead[i];
}
return tmp;
}
}
InputStreamPacket encData;
InputStream encStream;
TruncatedStream truncStream;
PGPDigestCalculator integrityCalculator;
PGPEncryptedData(
InputStreamPacket encData)
{
this.encData = encData;
}
/**
* Return the raw input stream for the data stream.
*
* Note this stream is shared with all other encryption methods in the same
* {@link PGPEncryptedDataList} and with any decryption methods in sub-classes, so consuming
* this stream will affect decryption.
*
* @return the encrypted data in this packet.
*/
public InputStream getInputStream()
{
return encData.getInputStream();
}
/**
* Checks whether the packet is integrity protected.
*
* @return true
if there is a modification detection code package associated with
* this stream
*/
public boolean isIntegrityProtected()
{
return (encData instanceof SymmetricEncIntegrityPacket);
}
/**
* Verifies the integrity of the packet against the modification detection code associated with
* it in the stream.
*
* Note: This can only be called after the message has been read.
*
* @return true
if the message verifies, false
otherwise.
* @throws PGPException if the message is not {@link #isIntegrityProtected() integrity
* protected}.
*/
public boolean verify()
throws PGPException, IOException
{
if (!this.isIntegrityProtected())
{
throw new PGPException("data not integrity protected.");
}
//
// make sure we are at the end.
//
while (encStream.read() >= 0)
{
// do nothing
}
//
// process the MDC packet
//
int[] lookAhead = truncStream.getLookAhead();
OutputStream dOut = integrityCalculator.getOutputStream();
dOut.write((byte)lookAhead[0]);
dOut.write((byte)lookAhead[1]);
byte[] digest = integrityCalculator.getDigest();
byte[] streamDigest = new byte[digest.length];
for (int i = 0; i != streamDigest.length; i++)
{
streamDigest[i] = (byte)lookAhead[i + 2];
}
return Arrays.constantTimeAreEqual(digest, streamDigest);
}
}