View Javadoc

1   /*
2    * $Id: KeyBasedEncryptionStrategy.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.pgp;
12  
13  import org.mule.RequestContext;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.lifecycle.InitialisationException;
16  import org.mule.api.security.CredentialsAccessor;
17  import org.mule.api.security.CryptoFailureException;
18  import org.mule.config.i18n.CoreMessages;
19  import org.mule.security.AbstractNamedEncryptionStrategy;
20  
21  import cryptix.message.EncryptedMessage;
22  import cryptix.message.EncryptedMessageBuilder;
23  import cryptix.message.LiteralMessageBuilder;
24  import cryptix.message.Message;
25  import cryptix.message.MessageFactory;
26  import cryptix.message.SignedMessageBuilder;
27  import cryptix.openpgp.PGPArmouredMessage;
28  import cryptix.openpgp.PGPDetachedSignatureMessage;
29  import cryptix.openpgp.PGPSignedMessage;
30  import cryptix.openpgp.packet.PGPSignaturePacket;
31  import cryptix.openpgp.provider.PGPDetachedSignatureMessageImpl;
32  import cryptix.pki.KeyBundle;
33  
34  import java.io.ByteArrayInputStream;
35  import java.util.Collection;
36  
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  public class KeyBasedEncryptionStrategy extends AbstractNamedEncryptionStrategy
41  {
42      /**
43       * logger used by this class
44       */
45      protected static final Log logger = LogFactory.getLog(KeyBasedEncryptionStrategy.class);
46  
47      private PGPKeyRing keyManager;
48      private CredentialsAccessor credentialsAccessor;
49  
50      public byte[] encrypt(byte[] data, Object cryptInfo) throws CryptoFailureException
51      {
52          try
53          {
54              PGPCryptInfo pgpCryptInfo;
55              KeyBundle publicKey;
56              
57              if (cryptInfo == null)
58              {
59                  MuleEvent event = RequestContext.getEvent();
60                  publicKey = keyManager.getKeyBundle((String)credentialsAccessor.getCredentials(
61                      event));
62                  
63                  pgpCryptInfo = new PGPCryptInfo(publicKey, false);
64              }
65              else
66              {
67                  pgpCryptInfo = (PGPCryptInfo)cryptInfo;
68                  publicKey = pgpCryptInfo.getKeyBundle();
69              }
70  
71              LiteralMessageBuilder lmb = LiteralMessageBuilder.getInstance("OpenPGP");
72  
73              lmb.init(data);
74  
75              Message msg = lmb.build();
76  
77              if (pgpCryptInfo.isSignRequested())
78              {
79                  SignedMessageBuilder smb = SignedMessageBuilder.getInstance("OpenPGP");
80  
81                  smb.init(msg);
82                  smb.addSigner(keyManager.getSecretKeyBundle(), keyManager.getSecretPassphrase().toCharArray());
83  
84                  msg = smb.build();
85              }
86  
87              EncryptedMessageBuilder emb = EncryptedMessageBuilder.getInstance("OpenPGP");
88              emb.init(msg);
89              emb.addRecipient(publicKey);
90              msg = emb.build();
91  
92              return new PGPArmouredMessage(msg).getEncoded();
93          }
94          catch (Exception e)
95          {
96              throw new CryptoFailureException(this, e);
97          }
98      }
99  
100     public byte[] decrypt(byte[] data, Object cryptInfo) throws CryptoFailureException
101     {
102         try
103         {
104             ByteArrayInputStream in = new ByteArrayInputStream(data);
105             MessageFactory mf = MessageFactory.getInstance("OpenPGP");
106             Collection<?> msgs = mf.generateMessages(in);
107             Message msg = (Message) msgs.iterator().next();
108 
109             if (msg instanceof EncryptedMessage)
110             {
111                 EncryptedMessage encryptedMessage = (EncryptedMessage) msg;
112                 KeyBundle secretKeyBundle = keyManager.getSecretKeyBundle();
113                 char[] passphrase = keyManager.getSecretPassphrase().toCharArray();
114                 msg = encryptedMessage.decrypt(secretKeyBundle, passphrase);
115                 
116                 applyStrongEncryptionWorkaround(msg);
117 
118                 return new PGPArmouredMessage(msg).getEncoded();
119             }
120         }
121         catch (Exception e)
122         {
123             throw new CryptoFailureException(this, e);
124         }
125 
126         return data;
127     }
128 
129     // cryptix seems to have trouble with some kinds of messsage encryption. Work around this
130     // by setting up the proper internal state first
131     private void applyStrongEncryptionWorkaround(Message msg) throws Exception
132     {
133         if (msg instanceof PGPSignedMessage)
134         {
135             PGPSignedMessage signedMessage = (PGPSignedMessage) msg;
136             
137             PGPDetachedSignatureMessage signature = signedMessage.getDetachedSignature();
138             if (signature instanceof PGPDetachedSignatureMessageImpl)
139             {
140                 PGPDetachedSignatureMessageImpl signatureImpl = 
141                     (PGPDetachedSignatureMessageImpl) signature;
142                 PGPSignaturePacket packet = signatureImpl.getPacket();
143                 if (packet.getVersion() == 4)
144                 {
145                     packet.parseSignatureSubPackets();
146                 }
147             }
148         }
149     }
150 
151     public void initialise() throws InitialisationException
152     {
153         try
154         {
155             java.security.Security.addProvider(new cryptix.jce.provider.CryptixCrypto());
156             java.security.Security.addProvider(new cryptix.openpgp.provider.CryptixOpenPGP());
157         }
158         catch (Exception e)
159         {
160             throw new InitialisationException(
161                 CoreMessages.failedToCreate("KeyBasedEncryptionStrategy"), e, this);
162         }
163     }
164 
165     public PGPKeyRing getKeyManager()
166     {
167         return keyManager;
168     }
169 
170     public void setKeyManager(PGPKeyRing keyManager)
171     {
172         this.keyManager = keyManager;
173     }
174 
175     public CredentialsAccessor getCredentialsAccessor() {
176         return credentialsAccessor;
177     }
178 
179     public void setCredentialsAccessor(CredentialsAccessor credentialsAccessor) {
180         this.credentialsAccessor = credentialsAccessor;
181     }
182 }