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

BcFixedLengthMGF1Padder.java « bc « crmf « cert « bouncycastle « org « java « main « src « pkix - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9fa53d6268cc3747c8d31259e111cb45bfa3f347 (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
package org.bouncycastle.cert.crmf.bc;

import java.security.SecureRandom;

import org.bouncycastle.cert.crmf.EncryptedValuePadder;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.generators.MGF1BytesGenerator;
import org.bouncycastle.crypto.params.MGFParameters;

/**
 * An encrypted value padder that uses MGF1 as the basis of the padding.
 */
public class BcFixedLengthMGF1Padder
    implements EncryptedValuePadder
{
    private int length;
    private SecureRandom random;
    private Digest dig = new SHA1Digest();

    /**
     * Create a padder to so that padded output will always be at least
     * length bytes long.
     *
     * @param length fixed length for padded output.
     */
    public BcFixedLengthMGF1Padder(int length)
    {
        this(length, null);
    }

    /**
     * Create a padder to so that padded output will always be at least
     * length bytes long, using the passed in source of randomness to
     * provide the random material for the padder.
     *
     * @param length fixed length for padded output.
     * @param random a source of randomness.
     */
    public BcFixedLengthMGF1Padder(int length, SecureRandom random)
    {
        this.length = length;
        this.random = random;
    }

    public byte[] getPaddedData(byte[] data)
    {
        byte[] bytes = new byte[length];
        byte[] seed = new byte[dig.getDigestSize()];
        byte[] mask = new byte[length - dig.getDigestSize()];

        if (random == null)
        {
            random = new SecureRandom();
        }

        random.nextBytes(seed);

        MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);

        maskGen.init(new MGFParameters(seed));

        maskGen.generateBytes(mask, 0, mask.length);

        System.arraycopy(seed, 0, bytes, 0, seed.length);
        System.arraycopy(data, 0, bytes, seed.length, data.length);

        for (int i = seed.length + data.length + 1; i != bytes.length; i++)
        {
            bytes[i] = (byte)(1 + random.nextInt(255));
        }

        for (int i = 0; i != mask.length; i++)
        {
            bytes[i + seed.length] ^= mask[i];
        }

        return bytes;
    }

    public byte[] getUnpaddedData(byte[] paddedData)
    {
        byte[] seed = new byte[dig.getDigestSize()];
        byte[] mask = new byte[length - dig.getDigestSize()];

        System.arraycopy(paddedData, 0, seed, 0, seed.length);

        MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);

        maskGen.init(new MGFParameters(seed));

        maskGen.generateBytes(mask, 0, mask.length);

        for (int i = 0; i != mask.length; i++)
        {
            paddedData[i + seed.length] ^= mask[i];
        }

        int end = 0;

        for (int i = paddedData.length - 1; i != seed.length; i--)
        {
            if (paddedData[i] == 0)
            {
                end = i;
                break;
            }
        }

        if (end == 0)
        {
            throw new IllegalStateException("bad padding in encoding");
        }

        byte[] data = new byte[end - seed.length];

        System.arraycopy(paddedData, seed.length, data, 0, data.length);

        return data;
    }
}