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

S2K.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: 6b36b3bc5ff71dce6d05c81d805fc53019e23005 (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
172
173
174
175
176
177
178
179
180
181
182
package org.spongycastle.bcpg;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;


/**
 * Parameter specifier for the PGP string-to-key password based key derivation function.
 * <p/>
 * In iterated mode, S2K takes a single byte iteration count specifier, which is converted to an
 * actual iteration count using a formula that grows the iteration count exponentially as the byte
 * value increases.<br/>
 * e.g. <code>0x01<code> == 1088 iterations, and <code>0xFF</code> == 65,011,712 iterations.
 */
public class S2K
    extends BCPGObject
{
    private static final int EXPBIAS = 6;

    /** Simple key generation. A single non-salted iteration of a hash function */
    public static final int SIMPLE = 0;
    /** Salted key generation. A single iteration of a hash function with a (unique) salt */
    public static final int SALTED = 1;
    /** Salted and iterated key generation. Multiple iterations of a hash function, with a salt */
    public static final int SALTED_AND_ITERATED = 3;

    public static final int GNU_DUMMY_S2K = 101;

    int       type;
    int       algorithm;
    byte[]    iv;
    int       itCount = -1;
    int       protectionMode = -1;

    S2K(
        InputStream    in)
        throws IOException
    {
        DataInputStream    dIn = new DataInputStream(in);

        type = dIn.read();
        algorithm = dIn.read();

        //
        // if this happens we have a dummy-S2K packet.
        //
        if (type != GNU_DUMMY_S2K)
        {
            if (type != 0)
            {
                iv = new byte[8];
                dIn.readFully(iv, 0, iv.length);

                if (type == 3)
                {
                    itCount = dIn.read();
                }
            }
        }
        else
        {
            dIn.read(); // G
            dIn.read(); // N
            dIn.read(); // U
            protectionMode = dIn.read(); // protection mode
        }
    }

    /**
     * Constructs a specifier for a {@link #SIMPLE simple} S2K generation.
     *
     * @param algorithm the {@link HashAlgorithmTags digest algorithm} to use.
     */
    public S2K(
        int        algorithm)
    {
        this.type = 0;
        this.algorithm = algorithm;
    }

    /**
     * Constructs a specifier for a {@link #SALTED salted} S2K generation.
     *
     * @param algorithm the {@link HashAlgorithmTags digest algorithm} to use.
     * @param iv the salt to apply to input to the key generation.
     */
    public S2K(
        int        algorithm,
        byte[]    iv)
    {
        this.type = 1;
        this.algorithm = algorithm;
        this.iv = iv;
    }

    /**
     * Constructs a specifier for a {@link #SALTED_AND_ITERATED salted and iterated} S2K generation.
     *
     * @param algorithm the {@link HashAlgorithmTags digest algorithm} to iterate.
     * @param iv the salt to apply to input to the key generation.
     * @param itCount the single byte iteration count specifier.
     */
    public S2K(
        int       algorithm,
        byte[]    iv,
        int       itCount)
    {
        this.type = 3;
        this.algorithm = algorithm;
        this.iv = iv;
        this.itCount = itCount;
    }

    /**
     * Gets the {@link HashAlgorithmTags digest algorithm} specified.
     */
    public int getType()
    {
        return type;
    }

    /**
     * Gets the {@link HashAlgorithmTags hash algorithm} for this S2K.
     */
    public int getHashAlgorithm()
    {
        return algorithm;
    }

    /**
     * Gets the iv/salt to use for the key generation.
     */
    public byte[] getIV()
    {
        return iv;
    }

    /**
     * Gets the actual (expanded) iteration count.
     */
    public long getIterationCount()
    {
        return (16 + (itCount & 15)) << ((itCount >> 4) + EXPBIAS);
    }

    /**
     * Gets the protection mode - only if GNU_DUMMY_S2K
     */
    public int getProtectionMode()
    {
        return protectionMode;
    }

    public void encode(
        BCPGOutputStream    out)
        throws IOException
    {
        out.write(type);
        out.write(algorithm);

        if (type != GNU_DUMMY_S2K)
        {
            if (type != 0)
            {
                out.write(iv);
            }

            if (type == 3)
            {
                out.write(itCount);
            }
        }
        else
        {
            out.write('G');
            out.write('N');
            out.write('U');
            out.write(protectionMode);
        }
    }
}