1 package org.bouncycastle.openpgp.operator.bc;
2 
3 import java.io.OutputStream;
4 import java.security.SecureRandom;
5 
6 import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
7 import org.bouncycastle.crypto.BlockCipher;
8 import org.bouncycastle.crypto.BufferedBlockCipher;
9 import org.bouncycastle.crypto.io.CipherOutputStream;
10 import org.bouncycastle.openpgp.PGPException;
11 import org.bouncycastle.openpgp.operator.PGPDataEncryptor;
12 import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder;
13 import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
14 
15 /**
16  * {@link PGPDataEncryptorBuilder} implementation that uses the Bouncy Castle lightweight API to
17  * implement cryptographic primitives.
18  */
19 public class BcPGPDataEncryptorBuilder
20     implements PGPDataEncryptorBuilder
21 {
22     private SecureRandom   random;
23     private boolean withIntegrityPacket;
24     private int encAlgorithm;
25 
26     /**
27      * Constructs a new data encryptor builder for a specified cipher type.
28      *
29      * @param encAlgorithm one of the {@link SymmetricKeyAlgorithmTags supported symmetric cipher
30      *            algorithms}. May not be {@link SymmetricKeyAlgorithmTags#NULL}.
31      */
BcPGPDataEncryptorBuilder(int encAlgorithm)32     public BcPGPDataEncryptorBuilder(int encAlgorithm)
33     {
34         this.encAlgorithm = encAlgorithm;
35 
36         if (encAlgorithm == 0)
37         {
38             throw new IllegalArgumentException("null cipher specified");
39         }
40     }
41 
42     /**
43      * Sets whether or not the resulting encrypted data will be protected using an integrity packet.
44      *
45      * @param withIntegrityPacket true if an integrity packet is to be included, false otherwise.
46      * @return the current builder.
47      */
setWithIntegrityPacket(boolean withIntegrityPacket)48     public BcPGPDataEncryptorBuilder setWithIntegrityPacket(boolean withIntegrityPacket)
49     {
50         this.withIntegrityPacket = withIntegrityPacket;
51 
52         return this;
53     }
54 
55     /**
56      * Provide a user defined source of randomness.
57      * <p>
58      * If no SecureRandom is configured, a default SecureRandom will be used.
59      * </p>
60      * @param random the secure random to be used.
61      * @return the current builder.
62      */
setSecureRandom(SecureRandom random)63     public BcPGPDataEncryptorBuilder setSecureRandom(SecureRandom random)
64     {
65         this.random = random;
66 
67         return this;
68     }
69 
getAlgorithm()70     public int getAlgorithm()
71     {
72         return encAlgorithm;
73     }
74 
getSecureRandom()75     public SecureRandom getSecureRandom()
76     {
77         if (random == null)
78         {
79             random = new SecureRandom();
80         }
81 
82         return random;
83     }
84 
build(byte[] keyBytes)85     public PGPDataEncryptor build(byte[] keyBytes)
86         throws PGPException
87     {
88         return new MyPGPDataEncryptor(keyBytes);
89     }
90 
91     private class MyPGPDataEncryptor
92         implements PGPDataEncryptor
93     {
94         private final BufferedBlockCipher c;
95 
MyPGPDataEncryptor(byte[] keyBytes)96         MyPGPDataEncryptor(byte[] keyBytes)
97             throws PGPException
98         {
99             BlockCipher engine = BcImplProvider.createBlockCipher(encAlgorithm);
100 
101             try
102             {
103                 c = BcUtil.createStreamCipher(true, engine, withIntegrityPacket, keyBytes);
104             }
105             catch (IllegalArgumentException e)
106             {
107                 throw new PGPException("invalid parameters: " + e.getMessage(), e);
108             }
109         }
110 
getOutputStream(OutputStream out)111         public OutputStream getOutputStream(OutputStream out)
112         {
113             return new CipherOutputStream(out, c);
114         }
115 
getIntegrityCalculator()116         public PGPDigestCalculator getIntegrityCalculator()
117         {
118             if (withIntegrityPacket)
119             {
120                 return new SHA1PGPDigestCalculator();
121             }
122 
123             return null;
124         }
125 
getBlockSize()126         public int getBlockSize()
127         {
128             return c.getBlockSize();
129         }
130     }
131 }
132