View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.core.impl.encryption;
17  
18  import org.apache.commons.codec.binary.Base64;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.config.property.ConfigContext;
21  import org.kuali.rice.core.api.encryption.EncryptionService;
22  
23  import javax.crypto.Cipher;
24  import javax.crypto.KeyGenerator;
25  import javax.crypto.SecretKey;
26  import javax.crypto.SecretKeyFactory;
27  import javax.crypto.spec.DESKeySpec;
28  import java.io.UnsupportedEncodingException;
29  import java.security.GeneralSecurityException;
30  import java.security.MessageDigest;
31  
32  /**
33   * Implementation of encryption service for demonstration. 
34   *
35   * @deprecated use {@link EncryptionServiceImpl} instead with the {@link org.kuali.rice.core.impl.encryption.EncryptionServiceImpl.DESEncryptionStrategy}
36   *
37   * @author Kuali Rice Team (rice.collab@kuali.org)
38   */
39  @Deprecated
40  public class DemonstrationGradeEncryptionServiceImpl implements EncryptionService {
41      public final static String ALGORITHM = "DES/ECB/PKCS5Padding";
42      public final static String HASH_ALGORITHM = "SHA"; 
43  
44      private final static String CHARSET = "UTF-8";
45  
46      private transient SecretKey desKey;
47  
48      private boolean isEnabled = false;
49  
50      public DemonstrationGradeEncryptionServiceImpl() throws Exception {
51          if (desKey != null) {
52              throw new RuntimeException("The secret key must be kept secret. Storing it in the Java source code is a really bad idea.");
53          }
54          String key = ConfigContext.getCurrentContextConfig().getProperty("encryption.key");
55          if (!StringUtils.isEmpty(key)) {
56              setSecretKey(key);
57          }
58      }
59      
60      public boolean isEnabled() {
61          return isEnabled;
62      }
63  
64      public String encrypt(Object valueToHide) throws GeneralSecurityException {
65      	checkEnabled();
66      	
67          if (valueToHide == null) {
68              return "";
69          }
70  
71          // Initialize the cipher for encryption
72          Cipher cipher = Cipher.getInstance(ALGORITHM);
73          cipher.init(Cipher.ENCRYPT_MODE, desKey);
74  
75          try {
76              // Our cleartext
77              byte[] cleartext = valueToHide.toString().getBytes(CHARSET);
78      
79              // Encrypt the cleartext
80              byte[] ciphertext = cipher.doFinal(cleartext);
81      
82              return new String(Base64.encodeBase64(ciphertext), CHARSET);
83          } catch (Exception e) {
84              throw new RuntimeException(e);
85          }
86  
87      }
88  
89      public String decrypt(String ciphertext) throws GeneralSecurityException {
90      	checkEnabled();
91      	
92          if (StringUtils.isBlank(ciphertext)) {
93              return "";
94          }
95  
96          // Initialize the same cipher for decryption
97          Cipher cipher = Cipher.getInstance(ALGORITHM);
98          cipher.init(Cipher.DECRYPT_MODE, desKey);
99  
100         try {
101             // un-Base64 encode the encrypted data
102             byte[] encryptedData = Base64.decodeBase64(ciphertext.getBytes(CHARSET));
103 
104             // Decrypt the ciphertext
105             byte[] cleartext1 = cipher.doFinal(encryptedData);
106             return new String(cleartext1, CHARSET);
107         } catch (UnsupportedEncodingException e) {
108             throw new RuntimeException(e);
109         }
110     }
111 
112     public byte[] encryptBytes(byte[] valueToHide) throws GeneralSecurityException {
113     	checkEnabled();
114     	
115         if (valueToHide == null) {
116             return new byte[0];
117         }
118 
119         // Initialize the cipher for encryption
120         Cipher cipher = Cipher.getInstance(ALGORITHM);
121         cipher.init(Cipher.ENCRYPT_MODE, desKey);
122 
123         // Our cleartext
124         byte[] cleartext = valueToHide;
125 
126         // Encrypt the cleartext
127         byte[] ciphertext = cipher.doFinal(cleartext);
128 
129         return ciphertext;
130     }
131 
132     public byte[] decryptBytes(byte[] ciphertext) throws GeneralSecurityException {
133     	checkEnabled();
134     	
135         if (ciphertext == null) {
136             return new byte[0];
137         }
138 
139         // Initialize the same cipher for decryption
140         Cipher cipher = Cipher.getInstance(ALGORITHM);
141         cipher.init(Cipher.DECRYPT_MODE, desKey);
142 
143         // un-Base64 encode the encrypted data
144         byte[] encryptedData = ciphertext;
145 
146         // Decrypt the ciphertext
147         byte[] cleartext1 = cipher.doFinal(encryptedData);
148         return cleartext1;
149     }
150     
151     /**
152      * 
153      * This method generates keys. This method is implementation specific and should not be present in any general purpose interface
154      * extracted from this class.
155      * 
156      * @return
157      * @throws Exception
158      */
159     public static String generateEncodedKey() throws Exception {
160         KeyGenerator keygen = KeyGenerator.getInstance("DES");
161         SecretKey desKey = keygen.generateKey();
162 
163         // Create the cipher
164         Cipher cipher = Cipher.getInstance(ALGORITHM);
165         cipher.init((Cipher.WRAP_MODE), desKey);
166         
167         SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
168         DESKeySpec desSpec = (DESKeySpec) desFactory.getKeySpec(desKey, javax.crypto.spec.DESKeySpec.class);
169         byte[] rawDesKey = desSpec.getKey();
170 
171         return new String(Base64.encodeBase64(rawDesKey));
172     }
173 
174     private SecretKey unwrapEncodedKey(String key) throws Exception {
175         KeyGenerator keygen = KeyGenerator.getInstance("DES");
176         SecretKey desKey = keygen.generateKey();
177 
178         // Create the cipher
179         Cipher cipher = Cipher.getInstance(ALGORITHM);
180         cipher.init((Cipher.UNWRAP_MODE), desKey);
181 
182         byte[] bytes = Base64.decodeBase64(key.getBytes());
183 
184         SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
185 
186         DESKeySpec keyspec = new DESKeySpec(bytes);
187         SecretKey k = desFactory.generateSecret(keyspec);
188 
189         return k;
190 
191     }
192 
193     /**
194      * Sets the secretKey attribute value.
195      * 
196      * @param secretKey The secretKey to set.
197      * @throws Exception
198      */
199     public void setSecretKey(String secretKey) throws Exception {
200     	if (!StringUtils.isEmpty(secretKey)) {
201     		desKey = this.unwrapEncodedKey(secretKey);
202     		isEnabled = true;
203     		// Create the cipher
204     		Cipher cipher = Cipher.getInstance(ALGORITHM);
205     		cipher.init((Cipher.WRAP_MODE), desKey);
206     	}
207     }
208 
209     /** Hash the value by converting to a string, running the hash algorithm, and then base64'ng the results.
210      * Returns a blank string if any problems occur or the input value is null or empty.
211      * 
212      * @see org.kuali.rice.krad.service.EncryptionService#hash(java.lang.Object)
213      */
214     public String hash(Object valueToHide) throws GeneralSecurityException {
215         if ( valueToHide == null || StringUtils.isEmpty( valueToHide.toString() ) ) {
216             return "";
217         }
218         try {
219             MessageDigest md = MessageDigest.getInstance(HASH_ALGORITHM);
220             return new String( Base64.encodeBase64( md.digest( valueToHide.toString().getBytes( CHARSET ) ) ), CHARSET );
221         } catch ( UnsupportedEncodingException ex ) {
222             // should never happen
223         }
224         return "";
225     }
226     
227     /**
228      * Performs a check to see if the encryption service is enabled.  If it is not then an
229      * IllegalStateException will be thrown.
230      */
231     protected void checkEnabled() {
232     	if (!isEnabled()) {
233     		throw new IllegalStateException("Illegal use of encryption service.  Ecryption service is disabled, to enable please configure 'encryption.key'.");
234     	}
235     }
236 
237     
238 
239 }