View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.module.pgp;
8   
9   import java.io.IOException;
10  import java.io.InputStream;
11  import java.io.OutputStream;
12  import java.security.SecureRandom;
13  import java.util.Date;
14  
15  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
16  
17  import org.apache.commons.lang.Validate;
18  import org.bouncycastle.bcpg.ArmoredOutputStream;
19  import org.bouncycastle.openpgp.PGPCompressedData;
20  import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
21  import org.bouncycastle.openpgp.PGPEncryptedData;
22  import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
23  import org.bouncycastle.openpgp.PGPLiteralData;
24  import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
25  import org.bouncycastle.openpgp.PGPPublicKey;
26  
27  public class EncryptStreamTransformer implements StreamTransformer
28  {
29      private static final long offset = 1 << 24;
30      
31      private InputStream toBeEncrypted;
32      private PGPPublicKey publicKey;
33  
34      private OutputStream pgpOutputStream;
35      private OutputStream compressedEncryptedOutputStream;
36      private OutputStream encryptedOutputStream;
37      private OutputStream armoredOut;
38      private long bytesWrote;
39  
40      public EncryptStreamTransformer(InputStream toBeEncrypted, PGPPublicKey publicKey) throws IOException
41      {
42          Validate.notNull(toBeEncrypted, "The toBeEncrypted should not be null");
43          Validate.notNull(publicKey, "The publicKey should not be null");
44  
45          this.toBeEncrypted = toBeEncrypted;
46          this.publicKey = publicKey;
47          this.bytesWrote = 0;
48      }
49  
50      /**
51       * {@inheritDoc}
52       */
53      public void initialize(OutputStream out) throws Exception
54      {
55          armoredOut = new ArmoredOutputStream(out);
56          PGPEncryptedDataGenerator encrDataGen = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, false,
57              new SecureRandom(), "BC");
58          encrDataGen.addMethod(this.publicKey);
59          encryptedOutputStream = encrDataGen.open(armoredOut, new byte[1 << 16]);
60  
61          PGPCompressedDataGenerator comprDataGen = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
62          compressedEncryptedOutputStream = comprDataGen.open(encryptedOutputStream);
63  
64          PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
65          pgpOutputStream = lData.open(compressedEncryptedOutputStream, PGPLiteralData.BINARY, "stream",
66              new Date(), new byte[1 << 16]);
67      }
68  
69      /**
70       * {@inheritDoc}
71       */
72      public boolean write(OutputStream out, AtomicLong bytesRequested) throws Exception
73      {
74          int len = 0;
75          byte[] buf = new byte[1 << 16];
76          boolean wroteSomething = false;
77          
78          while (bytesRequested.get() + offset > bytesWrote && (len = this.toBeEncrypted.read(buf)) > 0)
79          {
80              pgpOutputStream.write(buf, 0, len);
81              bytesWrote = bytesWrote + len;
82              wroteSomething = true;
83          }
84  
85          if (wroteSomething && len <= 0)
86          {
87              pgpOutputStream.close();
88              compressedEncryptedOutputStream.close();
89              encryptedOutputStream.close();
90              armoredOut.close();
91              toBeEncrypted.close();
92              return true;
93          }
94  
95          return false;
96      }
97  }