aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java')
-rw-r--r--libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java159
1 files changed, 159 insertions, 0 deletions
diff --git a/libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java b/libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java
new file mode 100644
index 000000000..678062a58
--- /dev/null
+++ b/libraries/spongycastle/pg/src/main/java/org/spongycastle/bcpg/SignatureSubpacketInputStream.java
@@ -0,0 +1,159 @@
+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;
+ }
+
+ if (l < 192)
+ {
+ bodyLen = l;
+ }
+ else if (l <= 223)
+ {
+ bodyLen = ((l - 192) << 8) + (in.read()) + 192;
+ }
+ else if (l == 255)
+ {
+ bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
+ }
+ else
+ {
+ // TODO Error?
+ }
+
+ 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, data);
+ case KEY_EXPIRE_TIME:
+ return new KeyExpirationTime(isCritical, data);
+ case EXPIRE_TIME:
+ return new SignatureExpirationTime(isCritical, data);
+ case REVOCABLE:
+ return new Revocable(isCritical, data);
+ case EXPORTABLE:
+ return new Exportable(isCritical, data);
+ case ISSUER_KEY_ID:
+ return new IssuerKeyID(isCritical, data);
+ case TRUST_SIG:
+ return new TrustSignature(isCritical, data);
+ case PREFERRED_COMP_ALGS:
+ case PREFERRED_HASH_ALGS:
+ case PREFERRED_SYM_ALGS:
+ return new PreferredAlgorithms(type, isCritical, data);
+ case KEY_FLAGS:
+ return new KeyFlags(isCritical, data);
+ case PRIMARY_USER_ID:
+ return new PrimaryUserID(isCritical, data);
+ case SIGNER_USER_ID:
+ return new SignerUserID(isCritical, data);
+ case NOTATION_DATA:
+ return new NotationData(isCritical, data);
+ }
+
+ return new SignatureSubpacket(type, isCritical, 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);
+ }
+}