Coverage Report - org.mule.module.pgp.DecryptStreamTransformer
 
Classes in this File Line Coverage Branch Coverage Complexity
DecryptStreamTransformer
0%
0/67
0%
0/28
0
 
 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.BufferedInputStream;
 10  
 import java.io.IOException;
 11  
 import java.io.InputStream;
 12  
 import java.io.OutputStream;
 13  
 import java.security.NoSuchProviderException;
 14  
 import java.util.Iterator;
 15  
 
 16  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
 17  
 
 18  
 import org.apache.commons.lang.Validate;
 19  
 import org.bouncycastle.openpgp.PGPCompressedData;
 20  
 import org.bouncycastle.openpgp.PGPEncryptedDataList;
 21  
 import org.bouncycastle.openpgp.PGPException;
 22  
 import org.bouncycastle.openpgp.PGPLiteralData;
 23  
 import org.bouncycastle.openpgp.PGPObjectFactory;
 24  
 import org.bouncycastle.openpgp.PGPOnePassSignature;
 25  
 import org.bouncycastle.openpgp.PGPOnePassSignatureList;
 26  
 import org.bouncycastle.openpgp.PGPPrivateKey;
 27  
 import org.bouncycastle.openpgp.PGPPublicKey;
 28  
 import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
 29  
 import org.bouncycastle.openpgp.PGPSecretKey;
 30  
 import org.bouncycastle.openpgp.PGPUtil;
 31  
 
 32  
 public class DecryptStreamTransformer implements StreamTransformer
 33  
 {
 34  
     private static final long offset = 1 << 24;
 35  
 
 36  
     private InputStream toBeDecrypted;
 37  
     private PGPPublicKey publicKey;
 38  
     private PGPSecretKey secretKey;
 39  
     private String password;
 40  
 
 41  
     private InputStream uncStream;
 42  
     private InputStream compressedStream;
 43  
     private InputStream clearStream;
 44  
     private long bytesWrote;
 45  
 
 46  
     public DecryptStreamTransformer(InputStream toBeDecrypted,
 47  
                                      PGPPublicKey publicKey,
 48  
                                      PGPSecretKey secretKey,
 49  
                                      String password) throws IOException
 50  0
     {
 51  0
         Validate.notNull(toBeDecrypted, "The toBeDecrypted should not be null");
 52  0
         Validate.notNull(publicKey, "The publicKey should not be null");
 53  0
         Validate.notNull(secretKey, "The secretKey should not be null");
 54  0
         Validate.notNull(password, "The password should not be null");
 55  
 
 56  0
         this.toBeDecrypted = toBeDecrypted;
 57  0
         this.publicKey = publicKey;
 58  0
         this.secretKey = secretKey;
 59  0
         this.password = password;
 60  0
         this.bytesWrote = 0;
 61  0
     }
 62  
 
 63  
     /**
 64  
      * {@inheritDoc}
 65  
      */
 66  
     public void initialize(OutputStream out) throws Exception
 67  
     {
 68  0
         InputStream decodedInputStream = PGPUtil.getDecoderStream(this.toBeDecrypted);
 69  0
         PGPObjectFactory pgpF = new PGPObjectFactory(decodedInputStream);
 70  0
         Object o = pgpF.nextObject();
 71  
 
 72  0
         if (o == null)
 73  
         {
 74  0
             throw new IllegalArgumentException("Invalid PGP message");
 75  
         }
 76  
 
 77  
         // the first object might be a PGP marker packet.
 78  
         PGPEncryptedDataList enc;
 79  0
         if (o instanceof PGPEncryptedDataList)
 80  
         {
 81  0
             enc = (PGPEncryptedDataList) o;
 82  
 
 83  
         }
 84  
         else
 85  
         {
 86  0
             enc = (PGPEncryptedDataList) pgpF.nextObject();
 87  
         }
 88  
 
 89  
         // This loop looks like it is ready for multiple encrypted
 90  
         // objects, but really only one is expected.
 91  0
         Iterator<?> it = enc.getEncryptedDataObjects();
 92  0
         PGPPublicKeyEncryptedData pbe = null;
 93  0
         PGPPrivateKey privateKey = null;
 94  0
         while (privateKey == null && it.hasNext())
 95  
         {
 96  0
             pbe = (PGPPublicKeyEncryptedData) it.next();
 97  0
             privateKey = getPrivateKey(pbe.getKeyID(), this.password);
 98  0
             if (privateKey == null)
 99  
             {
 100  0
                 throw new IllegalArgumentException("Failed to find private key with ID " + pbe.getKeyID());
 101  
             }
 102  
         }
 103  
 
 104  0
         clearStream = pbe.getDataStream(privateKey, "BC");
 105  0
         PGPObjectFactory plainFact = new PGPObjectFactory(clearStream);
 106  
 
 107  0
         o = plainFact.nextObject();
 108  0
         PGPOnePassSignature signature = null;
 109  0
         if (o instanceof PGPOnePassSignatureList)
 110  
         {
 111  0
             PGPOnePassSignatureList list = (PGPOnePassSignatureList) o;
 112  0
             signature = list.get(0);
 113  0
             signature.initVerify(this.publicKey, "BC");
 114  
             // TODO verify signature
 115  
             // signature.verify(null);
 116  0
             o = plainFact.nextObject();
 117  
         }
 118  
 
 119  0
         compressedStream = null;
 120  0
         if (o instanceof PGPCompressedData)
 121  
         {
 122  0
             PGPCompressedData cData = (PGPCompressedData) o;
 123  0
             compressedStream = new BufferedInputStream(cData.getDataStream());
 124  0
             PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);
 125  0
             Object streamData = pgpFact.nextObject();
 126  0
             o = streamData;
 127  
         }
 128  
 
 129  0
         if (o instanceof PGPLiteralData)
 130  
         {
 131  0
             PGPLiteralData ld = (PGPLiteralData) o;
 132  0
             uncStream = ld.getInputStream();
 133  0
         }
 134  
         else
 135  
         {
 136  0
             throw new PGPException("input is not PGPLiteralData - type unknown.");
 137  
         }
 138  0
     }
 139  
 
 140  
     /**
 141  
      * {@inheritDoc}
 142  
      */
 143  
     public boolean write(OutputStream out, AtomicLong bytesRequested) throws Exception
 144  
     {
 145  0
         int len = 0;
 146  0
         byte[] buf = new byte[1 << 16];
 147  0
         boolean wroteSomething = false;
 148  
 
 149  0
         while (bytesRequested.get() + offset > bytesWrote && (len = uncStream.read(buf)) > 0)
 150  
         {
 151  0
             out.write(buf, 0, len);
 152  0
             bytesWrote = bytesWrote + len;
 153  0
             wroteSomething = true;
 154  
         }
 155  
 
 156  0
         if (wroteSomething && len <= 0)
 157  
         {
 158  0
             uncStream.close();
 159  0
             if (compressedStream != null)
 160  
             {
 161  0
                 compressedStream.close();
 162  
             }
 163  0
             clearStream.close();
 164  0
             return true;
 165  
         }
 166  
 
 167  0
         return false;
 168  
     }
 169  
 
 170  
     private PGPPrivateKey getPrivateKey(long keyID, String pass) throws PGPException, NoSuchProviderException
 171  
     {
 172  0
         PGPSecretKey pgpSecKey = this.secretKey;
 173  0
         if (pgpSecKey == null)
 174  
         {
 175  0
             return null;
 176  
         }
 177  
         else
 178  
         {
 179  0
             return pgpSecKey.extractPrivateKey(pass.toCharArray(), "BC");
 180  
         }
 181  
     }
 182  
 }