aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/BufferedAsymmetricBlockCipher.java
blob: 9cefae1491b71a0970c115bcdd3b27d1f4644bfa (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
166
167
168
169
170
171
package org.spongycastle.crypto;

/**
 * a buffer wrapper for an asymmetric block cipher, allowing input
 * to be accumulated in a piecemeal fashion until final processing.
 */
public class BufferedAsymmetricBlockCipher
{
    protected byte[]        buf;
    protected int           bufOff;

    private final AsymmetricBlockCipher   cipher;

    /**
     * base constructor.
     *
     * @param cipher the cipher this buffering object wraps.
     */
    public BufferedAsymmetricBlockCipher(
        AsymmetricBlockCipher     cipher)
    {
        this.cipher = cipher;
    }

    /**
     * return the underlying cipher for the buffer.
     *
     * @return the underlying cipher for the buffer.
     */
    public AsymmetricBlockCipher getUnderlyingCipher()
    {
        return cipher;
    }

    /**
     * return the amount of data sitting in the buffer.
     *
     * @return the amount of data sitting in the buffer.
     */
    public int getBufferPosition()
    {
        return bufOff;
    }

    /**
     * initialise the buffer and the underlying cipher.
     *
     * @param forEncryption if true the cipher is initialised for
     *  encryption, if false for decryption.
     * @param params the key and other data required by the cipher.
     */
    public void init(
        boolean             forEncryption,
        CipherParameters    params)
    {
        reset();

        cipher.init(forEncryption, params);

        //
        // we allow for an extra byte where people are using their own padding
        // mechanisms on a raw cipher.
        //
        buf = new byte[cipher.getInputBlockSize() + (forEncryption ? 1 : 0)];
        bufOff = 0;
    }

    /**
     * returns the largest size an input block can be.
     *
     * @return maximum size for an input block.
     */
    public int getInputBlockSize()
    {
        return cipher.getInputBlockSize();
    }

    /**
     * returns the maximum size of the block produced by this cipher.
     *
     * @return maximum size of the output block produced by the cipher.
     */
    public int getOutputBlockSize()
    {
        return cipher.getOutputBlockSize();
    }

    /**
     * add another byte for processing.
     * 
     * @param in the input byte.
     */
    public void processByte(
        byte        in)
    {
        if (bufOff >= buf.length)
        {
            throw new DataLengthException("attempt to process message too long for cipher");
        }

        buf[bufOff++] = in;
    }

    /**
     * add len bytes to the buffer for processing.
     *
     * @param in the input data
     * @param inOff offset into the in array where the data starts
     * @param len the length of the block to be processed.
     */
    public void processBytes(
        byte[]      in,
        int         inOff,
        int         len)
    {
        if (len == 0)
        {
            return;
        }

        if (len < 0)
        {
            throw new IllegalArgumentException("Can't have a negative input length!");
        }

        if (bufOff + len > buf.length)
        {
            throw new DataLengthException("attempt to process message too long for cipher");
        }

        System.arraycopy(in, inOff, buf, bufOff, len);
        bufOff += len;
    }

    /**
     * process the contents of the buffer using the underlying
     * cipher.
     *
     * @return the result of the encryption/decryption process on the
     * buffer.
     * @exception InvalidCipherTextException if we are given a garbage block.
     */
    public byte[] doFinal()
        throws InvalidCipherTextException
    {
        byte[] out = cipher.processBlock(buf, 0, bufOff);

        reset();

        return out;
    }

    /**
     * Reset the buffer and the underlying cipher.
     */
    public void reset()
    {
        /*
         * clean the buffer.
         */
        if (buf != null)
        {
            for (int i = 0; i < buf.length; i++)
            {
                buf[i] = 0;
            }
        }

        bufOff = 0;
    }
}