aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/PGPKeyRingGenerator.java
blob: dc3fae7115334f3a30b25645f608c401324de7b5 (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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
package org.spongycastle.openpgp;

import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.PublicSubkeyPacket;
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;

/**
 * Generator for a PGP master and subkey ring. This class will generate
 * both the secret and public key rings
 */
public class PGPKeyRingGenerator
{    
    List                                keys = new ArrayList();

    private PBESecretKeyEncryptor       keyEncryptor;
    private PGPDigestCalculator checksumCalculator;
    private PGPKeyPair                  masterKey;
    private PGPSignatureSubpacketVector hashedPcks;
    private PGPSignatureSubpacketVector unhashedPcks;
    private PGPContentSignerBuilder     keySignerBuilder;
    
    /**
     * Create a new key ring generator using old style checksumming. It is recommended to use
     * SHA1 checksumming where possible.
     * 
     * @param certificationLevel the certification level for keys on this ring.
     * @param masterKey the master key pair.
     * @param id the id to be associated with the ring.
     * @param encAlgorithm the algorithm to be used to protect secret keys.
     * @param passPhrase the passPhrase to be used to protect secret keys.
     * @param hashedPcks packets to be included in the certification hash.
     * @param unhashedPcks packets to be attached unhashed to the certification.
     * @param rand input secured random
     * @param provider the provider to use for encryption.
     * 
     * @throws PGPException
     * @throws NoSuchProviderException
     * @deprecated   use method taking PBESecretKeyDecryptor
     */
    public PGPKeyRingGenerator(
        int                            certificationLevel,
        PGPKeyPair                     masterKey,
        String                         id,
        int                            encAlgorithm,
        char[]                         passPhrase,
        PGPSignatureSubpacketVector    hashedPcks,
        PGPSignatureSubpacketVector    unhashedPcks,
        SecureRandom                   rand,
        String                         provider)
        throws PGPException, NoSuchProviderException
    {
        this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPcks, unhashedPcks, rand, provider);
    }

    /**
     * Create a new key ring generator.
     * 
     * @param certificationLevel the certification level for keys on this ring.
     * @param masterKey the master key pair.
     * @param id the id to be associated with the ring.
     * @param encAlgorithm the algorithm to be used to protect secret keys.
     * @param passPhrase the passPhrase to be used to protect secret keys.
     * @param useSHA1 checksum the secret keys with SHA1 rather than the older 16 bit checksum.
     * @param hashedPcks packets to be included in the certification hash.
     * @param unhashedPcks packets to be attached unhashed to the certification.
     * @param rand input secured random
     * @param provider the provider to use for encryption.
     * 
     * @throws PGPException
     * @throws NoSuchProviderException
     * @deprecated   use method taking PBESecretKeyDecryptor
     */
    public PGPKeyRingGenerator(
        int                            certificationLevel,
        PGPKeyPair                     masterKey,
        String                         id,
        int                            encAlgorithm,
        char[]                         passPhrase,
        boolean                        useSHA1,
        PGPSignatureSubpacketVector    hashedPcks,
        PGPSignatureSubpacketVector    unhashedPcks,
        SecureRandom                   rand,
        String                         provider)
        throws PGPException, NoSuchProviderException
    {
        this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSHA1, hashedPcks, unhashedPcks, rand, PGPUtil.getProvider(provider));
    }

    /**
     * Create a new key ring generator.
     *
     * @param certificationLevel the certification level for keys on this ring.
     * @param masterKey the master key pair.
     * @param id the id to be associated with the ring.
     * @param encAlgorithm the algorithm to be used to protect secret keys.
     * @param passPhrase the passPhrase to be used to protect secret keys.
     * @param useSHA1 checksum the secret keys with SHA1 rather than the older 16 bit checksum.
     * @param hashedPcks packets to be included in the certification hash.
     * @param unhashedPcks packets to be attached unhashed to the certification.
     * @param rand input secured random
     * @param provider the provider to use for encryption.
     *
     * @throws PGPException
     * @throws NoSuchProviderException
     * @deprecated  use method taking PBESecretKeyEncryptor
     */
    public PGPKeyRingGenerator(
        int                            certificationLevel,
        PGPKeyPair                     masterKey,
        String                         id,
        int                            encAlgorithm,
        char[]                         passPhrase,
        boolean                        useSHA1,
        PGPSignatureSubpacketVector    hashedPcks,
        PGPSignatureSubpacketVector    unhashedPcks,
        SecureRandom                   rand,
        Provider                       provider)
        throws PGPException, NoSuchProviderException
    {
        this.masterKey = masterKey;
        this.hashedPcks = hashedPcks;
        this.unhashedPcks = unhashedPcks;
        this.keyEncryptor = new JcePBESecretKeyEncryptorBuilder(encAlgorithm).setProvider(provider).setSecureRandom(rand).build(passPhrase);
        this.checksumCalculator = convertSHA1Flag(useSHA1);
        this.keySignerBuilder = new JcaPGPContentSignerBuilder(masterKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);

        keys.add(new PGPSecretKey(certificationLevel, masterKey, id, checksumCalculator, hashedPcks, unhashedPcks, keySignerBuilder, keyEncryptor));
    }

    /**
     * Create a new key ring generator.
     *
     * @param certificationLevel
     * @param masterKey
     * @param id
     * @param checksumCalculator
     * @param hashedPcks
     * @param unhashedPcks
     * @param keySignerBuilder
     * @param keyEncryptor
     * @throws PGPException
     */
    public PGPKeyRingGenerator(
        int                            certificationLevel,
        PGPKeyPair                     masterKey,
        String                         id,
        PGPDigestCalculator checksumCalculator,
        PGPSignatureSubpacketVector    hashedPcks,
        PGPSignatureSubpacketVector    unhashedPcks,
        PGPContentSignerBuilder        keySignerBuilder,
        PBESecretKeyEncryptor          keyEncryptor)
        throws PGPException
    {
        this.masterKey = masterKey;
        this.keyEncryptor = keyEncryptor;
        this.checksumCalculator = checksumCalculator;
        this.keySignerBuilder = keySignerBuilder;
        this.hashedPcks = hashedPcks;
        this.unhashedPcks = unhashedPcks;

        keys.add(new PGPSecretKey(certificationLevel, masterKey, id, checksumCalculator, hashedPcks, unhashedPcks, keySignerBuilder, keyEncryptor));
    }

    /**
     * Add a sub key to the key ring to be generated with default certification and inheriting
     * the hashed/unhashed packets of the master key.
     * 
     * @param keyPair
     * @throws PGPException
     */
    public void addSubKey(
        PGPKeyPair    keyPair) 
        throws PGPException
    {
        addSubKey(keyPair, hashedPcks, unhashedPcks);
    }
    
    /**
     * Add a subkey with specific hashed and unhashed packets associated with it and default
     * certification. 
     * 
     * @param keyPair public/private key pair.
     * @param hashedPcks hashed packet values to be included in certification.
     * @param unhashedPcks unhashed packets values to be included in certification.
     * @throws PGPException
     */
    public void addSubKey(
        PGPKeyPair                  keyPair,
        PGPSignatureSubpacketVector hashedPcks,
        PGPSignatureSubpacketVector unhashedPcks) 
        throws PGPException
    {
        try
        {
            //
            // generate the certification
            //
            PGPSignatureGenerator  sGen = new PGPSignatureGenerator(keySignerBuilder);

            sGen.init(PGPSignature.SUBKEY_BINDING, masterKey.getPrivateKey());

            sGen.setHashedSubpackets(hashedPcks);
            sGen.setUnhashedSubpackets(unhashedPcks);

            List                 subSigs = new ArrayList();
            
            subSigs.add(sGen.generateCertification(masterKey.getPublicKey(), keyPair.getPublicKey()));
            
            keys.add(new PGPSecretKey(keyPair.getPrivateKey(), new PGPPublicKey(keyPair.getPublicKey(), null, subSigs), checksumCalculator, keyEncryptor));
        }
        catch (PGPException e)
        {
            throw e;
        } 
        catch (Exception e)
        {
            throw new PGPException("exception adding subkey: ", e);
        }
    }
    
    /**
     * Return the secret key ring.
     * 
     * @return a secret key ring.
     */
    public PGPSecretKeyRing generateSecretKeyRing()
    {
        return new PGPSecretKeyRing(keys);
    }
    
    /**
     * Return the public key ring that corresponds to the secret key ring.
     * 
     * @return a public key ring.
     */
    public PGPPublicKeyRing generatePublicKeyRing()
    {
        Iterator it = keys.iterator();
        List     pubKeys = new ArrayList();
        
        pubKeys.add(((PGPSecretKey)it.next()).getPublicKey());
        
        while (it.hasNext())
        {
            PGPPublicKey k = new PGPPublicKey(((PGPSecretKey)it.next()).getPublicKey());
            
            k.publicPk = new PublicSubkeyPacket(k.getAlgorithm(), k.getCreationTime(), k.publicPk.getKey());
            
            pubKeys.add(k);
        }
        
        return new PGPPublicKeyRing(pubKeys);
    }

    private static PGPDigestCalculator convertSHA1Flag(boolean useSHA1)
        throws PGPException
    {
        return useSHA1 ? new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1) : null;
    }
}