Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SignatureSubpacketInputStream.java « bcpg « spongycastle « org « java « main « src « pg - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 678062a5884fa446bf140840bc65c5e4af2523b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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);
    }
}