package org.bouncycastle.bcpg; import java.io.*; import org.bouncycastle.bcpg.sig.Exportable; import org.bouncycastle.bcpg.sig.IssuerKeyID; import org.bouncycastle.bcpg.sig.KeyExpirationTime; import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.bcpg.sig.PreferredAlgorithms; import org.bouncycastle.bcpg.sig.PrimaryUserID; import org.bouncycastle.bcpg.sig.Revocable; import org.bouncycastle.bcpg.sig.SignatureCreationTime; import org.bouncycastle.bcpg.sig.SignatureExpirationTime; import org.bouncycastle.bcpg.sig.SignerUserID; import org.bouncycastle.bcpg.sig.TrustSignature; /** * 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(); } private void readFully( byte[] buf, int off, int len) throws IOException { if (len > 0) { int b = this.read(); if (b < 0) { throw new EOFException(); } buf[off] = (byte)b; off++; len--; } while (len > 0) { int l = in.read(buf, off, len); if (l < 0) { throw new EOFException(); } off += l; len -= l; } } 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(); } int tag = in.read(); if (tag < 0) { throw new EOFException("unexpected EOF reading signature sub packet"); } byte[] data = new byte[bodyLen - 1]; this.readFully(data, 0, data.length); boolean isCritical = ((tag & 0x80) != 0); int type = tag & 0x7f; 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); } return new SignatureSubpacket(type, isCritical, data); } }