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

PGPEncryptedData.java « openpgp « spongycastle « org « java « main « src « pg - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6f5f404321e9b1cec68cc439cac94d086aeb8b58 (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
160
161
162
163
164
165
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.
 * <p/>
 * 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.
     * <p/>
     * 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 <code>true</code> 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.
     * <p/>
     * Note: This can only be called after the message has been read.
     *
     * @return <code>true</code> if the message verifies, <code>false</code> 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);
    }
}