org.spongycastle.bcpg.SignatureSubpacketInputStream 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.bcpg;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import org.spongycastle.bcpg.sig.Exportable;
import org.spongycastle.bcpg.sig.IssuerKeyID;
import org.spongycastle.bcpg.sig.KeyExpirationTime;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.bcpg.sig.NotationData;
import org.spongycastle.bcpg.sig.PreferredAlgorithms;
import org.spongycastle.bcpg.sig.PrimaryUserID;
import org.spongycastle.bcpg.sig.Revocable;
import org.spongycastle.bcpg.sig.SignatureCreationTime;
import org.spongycastle.bcpg.sig.SignatureExpirationTime;
import org.spongycastle.bcpg.sig.SignerUserID;
import org.spongycastle.bcpg.sig.TrustSignature;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.io.Streams;
/**
* reader for signature sub-packets
*/
public class SignatureSubpacketInputStream
extends InputStream
implements SignatureSubpacketTags
{
InputStream in;
public SignatureSubpacketInputStream(
InputStream in)
{
this.in = in;
}
public int available()
throws IOException
{
return in.available();
}
public int read()
throws IOException
{
return in.read();
}
public SignatureSubpacket readPacket()
throws IOException
{
int l = this.read();
int bodyLen = 0;
if (l < 0)
{
return null;
}
boolean isLongLength = false;
if (l < 192)
{
bodyLen = l;
}
else if (l <= 223)
{
bodyLen = ((l - 192) << 8) + (in.read()) + 192;
}
else if (l == 255)
{
isLongLength = true;
bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
}
else
{
throw new IOException("unexpected length header");
}
int tag = in.read();
if (tag < 0)
{
throw new EOFException("unexpected EOF reading signature sub packet");
}
byte[] data = new byte[bodyLen - 1];
//
// this may seem a bit strange but it turns out some applications miscode the length
// in fixed length fields, so we check the length we do get, only throwing an exception if
// we really cannot continue
//
int bytesRead = Streams.readFully(in, data);
boolean isCritical = ((tag & 0x80) != 0);
int type = tag & 0x7f;
if (bytesRead != data.length)
{
switch (type)
{
case CREATION_TIME:
data = checkData(data, 4, bytesRead, "Signature Creation Time");
break;
case ISSUER_KEY_ID:
data = checkData(data, 8, bytesRead, "Issuer");
break;
case KEY_EXPIRE_TIME:
data = checkData(data, 4, bytesRead, "Signature Key Expiration Time");
break;
case EXPIRE_TIME:
data = checkData(data, 4, bytesRead, "Signature Expiration Time");
break;
default:
throw new EOFException("truncated subpacket data.");
}
}
switch (type)
{
case CREATION_TIME:
return new SignatureCreationTime(isCritical, isLongLength, data);
case KEY_EXPIRE_TIME:
return new KeyExpirationTime(isCritical, isLongLength, data);
case EXPIRE_TIME:
return new SignatureExpirationTime(isCritical, isLongLength, data);
case REVOCABLE:
return new Revocable(isCritical, isLongLength, data);
case EXPORTABLE:
return new Exportable(isCritical, isLongLength, data);
case ISSUER_KEY_ID:
return new IssuerKeyID(isCritical, isLongLength, data);
case TRUST_SIG:
return new TrustSignature(isCritical, isLongLength, data);
case PREFERRED_COMP_ALGS:
case PREFERRED_HASH_ALGS:
case PREFERRED_SYM_ALGS:
return new PreferredAlgorithms(type, isCritical, isLongLength, data);
case KEY_FLAGS:
return new KeyFlags(isCritical, isLongLength, data);
case PRIMARY_USER_ID:
return new PrimaryUserID(isCritical, isLongLength, data);
case SIGNER_USER_ID:
return new SignerUserID(isCritical, isLongLength, data);
case NOTATION_DATA:
return new NotationData(isCritical, isLongLength, data);
}
return new SignatureSubpacket(type, isCritical, isLongLength, data);
}
private byte[] checkData(byte[] data, int expected, int bytesRead, String name)
throws EOFException
{
if (bytesRead != expected)
{
throw new EOFException("truncated " + name + " subpacket data.");
}
return Arrays.copyOfRange(data, 0, expected);
}
}