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.junit.After;
20  import org.junit.Before;
21  import org.junit.Test;
22  import org.kuali.rice.core.api.config.property.ConfigContext;
23  import org.kuali.rice.core.framework.config.property.SimpleConfig;
24  
25  import javax.crypto.KeyGenerator;
26  import javax.crypto.SecretKey;
27  import javax.crypto.SecretKeyFactory;
28  import javax.crypto.spec.DESKeySpec;
29  import javax.crypto.spec.DESedeKeySpec;
30  import java.util.Arrays;
31  
32  import static org.junit.Assert.*;
33  
34  /**
35   * Unit test for {@link EncryptionServiceImpl}
36   *
37   * @author Eric Westfall
38   */
39  public class EncryptionServiceImplTest {
40  
41      private EncryptionServiceImpl service;
42      private SimpleConfig config;
43      private String desKey;
44      private String desedeKey;
45  
46      @Before
47      public void setUp() throws Exception {
48          this.service = new EncryptionServiceImpl();
49          this.config = new SimpleConfig();
50          ConfigContext.init(this.config);
51          this.desKey = generateDESKey();
52          this.desedeKey = generateDESedeKey();
53      }
54  
55      @After
56      public void tearDown() {
57          if (ConfigContext.isInitialized()) {
58              ConfigContext.destroy();
59          }
60      }
61  
62      private String generateDESKey() throws Exception {
63          KeyGenerator keygen = KeyGenerator.getInstance("DES");
64          SecretKey desKey = keygen.generateKey();
65          SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
66          DESKeySpec desSpec = (DESKeySpec) desFactory.getKeySpec(desKey, javax.crypto.spec.DESKeySpec.class);
67          byte[] rawDesKey = desSpec.getKey();
68          return new String(Base64.encodeBase64(rawDesKey));
69      }
70  
71      private String generateDESedeKey() throws Exception {
72          KeyGenerator keygen = KeyGenerator.getInstance("DESede");
73          SecretKey desedeKey = keygen.generateKey();
74  
75          SecretKeyFactory desedeFactory = SecretKeyFactory.getInstance("DESede");
76          DESedeKeySpec desedeSpec = (DESedeKeySpec) desedeFactory.getKeySpec(desedeKey, javax.crypto.spec.DESedeKeySpec.class);
77          byte[] rawDesedeKey = desedeSpec.getKey();
78          return new String(Base64.encodeBase64(rawDesedeKey));
79      }
80  
81      @Test
82      public void testDisabledEncryptionService() throws Exception {
83          service.afterPropertiesSet();
84          // service should not be enabled since we never set a secret key
85          assertFalse(service.isEnabled());
86      }
87  
88      /**
89       * The default algorithm used should be DES so that it's compatible with the {@link DemonstrationGradeEncryptionServiceImpl}
90       */
91      @Test
92      public void testDefaultAlgorithmIsDES() throws Exception {
93          service.afterPropertiesSet();
94          assertTrue(service.getEncryptionStrategy().getTransformation().startsWith("DES/"));
95      }
96  
97      /**
98       * Encryption service should be enabled once a key is injected
99       */
100     @Test
101     public void testInjectSecretKey() throws Exception {
102         service.setSecretKey(desKey);
103         service.afterPropertiesSet();
104         assertTrue(service.isEnabled());
105     }
106 
107     @Test
108     public void testLoadSecretKeyFromConfig() throws Exception {
109         // create one instance where it's loaded from config and one where it's injected, make sure they encrypt the same way
110         config.putProperty("encryption.key", desKey);
111         service.afterPropertiesSet();
112 
113         EncryptionServiceImpl service2 = new EncryptionServiceImpl();
114         service2.setSecretKey(desKey);
115         service2.afterPropertiesSet();
116 
117         String valueToEncrypt = "abcdefg";
118         String encrypted1 = service.encrypt(valueToEncrypt);
119         String encrypted2 = service2.encrypt(valueToEncrypt);
120 
121         assertEquals("encrypted values should be the same", encrypted1, encrypted2);
122     }
123 
124 
125     @Test(expected = IllegalArgumentException.class)
126     public void testInvalidAlgorithm() throws Exception {
127         config.putProperty("encryption.algorithm", "gobbletygook");
128         service.afterPropertiesSet();
129     }
130 
131     @Test
132     public void testDESedeEncryptDecrypt() throws Exception {
133         service.setSecretKey(desedeKey);
134         config.putProperty("encryption.algorithm", "DESede");
135         service.afterPropertiesSet();
136 
137         String valueToEncrypt = "abc";
138         String encrypted = service.encrypt(valueToEncrypt);
139 
140         // now decrypt it, make sure it's the same
141         assertEquals(valueToEncrypt, service.decrypt(encrypted));
142     }
143 
144     @Test
145     public void testDESedeEncryptDecryptBytes() throws Exception {
146         service.setSecretKey(desedeKey);
147         config.putProperty("encryption.algorithm", "DESede");
148         service.afterPropertiesSet();
149 
150         byte[] bytesToEncrypt = { 1, 7, 4, 3};
151         byte[] encrypted = service.encryptBytes(bytesToEncrypt);
152 
153         // now decrypt it, make sure it's the same
154         assertTrue(Arrays.equals(bytesToEncrypt, service.decryptBytes(encrypted)));
155     }
156 
157     @Test
158     public void testDESEncryptDecrypt() throws Exception {
159         service.setSecretKey(desKey);
160         config.putProperty("encryption.algorithm", "DES");
161         service.afterPropertiesSet();
162 
163         String valueToEncrypt = "abc";
164         String encrypted = service.encrypt(valueToEncrypt);
165 
166         // now decrypt it, make sure it's the same
167         assertEquals(valueToEncrypt, service.decrypt(encrypted));
168     }
169 
170     @Test
171     public void testDESEncryptDecryptBytes() throws Exception {
172         service.setSecretKey(desKey);
173         config.putProperty("encryption.algorithm", "DES");
174         service.afterPropertiesSet();
175 
176         byte[] bytesToEncrypt = { 1, 7, 4, 3};
177         byte[] encrypted = service.encryptBytes(bytesToEncrypt);
178 
179         // now decrypt it, make sure it's the same
180         assertTrue(Arrays.equals(bytesToEncrypt, service.decryptBytes(encrypted)));
181     }
182 
183     @Test(expected = IllegalStateException.class)
184     public void testEncryptWhenDisabled() throws Exception {
185         service.afterPropertiesSet();
186         service.encrypt("yo");
187     }
188 
189     @Test
190     public void testEncryptNullValue() throws Exception {
191         service.setSecretKey(desKey);
192         service.afterPropertiesSet();
193         assertEquals("", service.encrypt(null));
194     }
195 
196     @Test
197     public void testEcryptNullByteArray() throws Exception {
198         service.setSecretKey(desKey);
199         service.afterPropertiesSet();
200         assertTrue(Arrays.equals(new byte[0], service.encryptBytes(null)));
201     }
202 
203     @Test
204     public void testDecryptNullValue() throws Exception {
205         service.setSecretKey(desKey);
206         service.afterPropertiesSet();
207         assertEquals("", service.decrypt(null));
208     }
209 
210     @Test
211     public void testDecryptBlankValue() throws Exception {
212         service.setSecretKey(desKey);
213         service.afterPropertiesSet();
214         assertEquals("", service.decrypt(""));
215     }
216 
217     @Test
218     public void testDecryptNullByteArray() throws Exception {
219         service.setSecretKey(desKey);
220         service.afterPropertiesSet();
221         assertTrue(Arrays.equals(new byte[0], service.decryptBytes(null)));
222     }
223 
224     @Test
225     public void testSetSecretKeyAfterInitialization() throws Exception {
226         service.afterPropertiesSet();
227         assertFalse(service.isEnabled());
228         service.setSecretKey(desKey);
229         assertTrue(service.isEnabled());
230 
231         // check that we can encrypt/decrypt
232         String valueToEncrypt = "cba";
233         assertEquals(valueToEncrypt, service.decrypt(service.encrypt(valueToEncrypt)));
234     }
235 
236     @Test
237     public void testHash() throws Exception {
238         service.afterPropertiesSet();
239 
240         String valueToHash = "hashme";
241         String hashed = service.hash(valueToHash);
242         assertNotNull(hashed);
243         assertEquals(hashed, service.hash(valueToHash));
244 
245     }
246 
247     @Test
248     public void testHashNullAndEmpty() throws Exception {
249         service.afterPropertiesSet();
250         assertEquals("", service.hash(null));
251         assertEquals("", service.hash(""));
252     }
253 
254     @Test(expected = IllegalStateException.class)
255     public void testInvalidCharset_Encrypt() throws Exception {
256         service.setCharset("INVALID");
257         service.setSecretKey(desKey);
258         service.afterPropertiesSet();
259         service.encrypt("test");
260     }
261 
262     @Test(expected = IllegalStateException.class)
263     public void testInvalidCharset_Decrypt() throws Exception {
264         service.setSecretKey(desKey);
265         service.afterPropertiesSet();
266         String encrypted = service.encrypt("test");
267         service.setCharset("INVALID");
268         service.decrypt(encrypted);
269     }
270 
271     @Test(expected = IllegalStateException.class)
272     public void testInvalidCharset_EncryptBytes() throws Exception {
273         service.setCharset("INVALID");
274         service.setSecretKey(desKey);
275         service.afterPropertiesSet();
276         service.encrypt("test".getBytes());
277     }
278 
279     @Test(expected = IllegalStateException.class)
280     public void testInvalidCharset_Hash() throws Exception {
281         service.setCharset("INVALID");
282         service.setSecretKey(desKey);
283         service.afterPropertiesSet();
284         service.hash("test");
285     }
286 
287 }