View Javadoc

1   /*
2    * Copyright 2007-2008 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.web.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.apache.commons.lang.StringUtils;
22  import org.junit.Test;
23  import org.kuali.rice.core.config.Config;
24  import org.kuali.rice.core.config.ConfigContext;
25  import org.kuali.rice.core.config.JAXBConfigImpl;
26  import org.kuali.rice.core.config.SimpleConfig;
27  import org.kuali.rice.core.service.EncryptionService;
28  import org.kuali.rice.core.service.impl.DemonstrationGradeEncryptionServiceImpl;
29  import org.kuali.rice.kns.service.KNSServiceLocator;
30  import org.kuali.rice.web.test.ServerTestBase;
31  
32  /**
33   * This is a class that tests the {@link DemonstrationGradeEncryptionServiceImpl} class
34   * 
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class DemonstrationGradeEncryptionServiceImplTest extends ServerTestBase {
38  
39      // it would be a terrible idea to ever use this particular secret key outside of this unit test
40      private final static String NOT_SO_SECRET_KEY_ONLY_INTENDED_FOR_TESTING = "sm3H8KUU8BTzpFULS9ME7g==";
41      private static final String TEST_VALUE = "77789";
42  
43      private static boolean failed = false;
44  
45      @Test
46      public void testEncrypt() throws Exception {
47          assertEquals(KNSServiceLocator.getNervousSystemContextBean(EncryptionService.class).decrypt(KNSServiceLocator.getNervousSystemContextBean(EncryptionService.class).encrypt(TEST_VALUE)), TEST_VALUE);
48          EncryptionService encryptionService = new DemonstrationGradeEncryptionServiceImpl();
49          ((DemonstrationGradeEncryptionServiceImpl) encryptionService).setSecretKey(NOT_SO_SECRET_KEY_ONLY_INTENDED_FOR_TESTING);
50  
51          String valueToHide = "The quick brown fox jumps over a lazy dog";
52          assertTrue("Byte array should be equivalent to the target String", valueToHide.equals(new String(valueToHide.getBytes())));
53          String encrypted = encryptionService.encrypt(valueToHide);
54  
55          // Verify the string can be decrypted:
56          String clearText = encryptionService.decrypt(encrypted);
57          assertTrue(clearText.equals(valueToHide));
58  
59          // Make sure it can be decrypted from a freshly created copy:
60          encryptionService = new DemonstrationGradeEncryptionServiceImpl();
61          ((DemonstrationGradeEncryptionServiceImpl) encryptionService).setSecretKey(NOT_SO_SECRET_KEY_ONLY_INTENDED_FOR_TESTING);
62          clearText = encryptionService.decrypt(encrypted);
63          assertTrue(clearText.equals(valueToHide));
64          System.err.println("This should be unintelligible: " + encrypted);
65          System.err.println("Here is a freshly generated secret key: " + ((DemonstrationGradeEncryptionServiceImpl) encryptionService).generateEncodedKey());
66  
67          encryptionService = KNSServiceLocator.getNervousSystemContextBean(EncryptionService.class);
68          valueToHide = "999999999";
69          // valueToHide = StringUtils.rightPad(valueToHide, 16);
70          encrypted = encryptionService.encrypt(valueToHide) + EncryptionService.ENCRYPTION_POST_PREFIX;
71          System.out.print(encrypted);
72          encrypted = StringUtils.stripEnd(encrypted, EncryptionService.ENCRYPTION_POST_PREFIX);
73          clearText = KNSServiceLocator.getNervousSystemContextBean(EncryptionService.class).decrypt(encrypted);
74          assertTrue(clearText.equals(valueToHide));
75  
76          valueToHide = "My friend Joe";
77          valueToHide = StringUtils.rightPad(valueToHide, 16);
78          encrypted = encryptionService.encrypt(valueToHide);
79          System.out.print(encrypted);
80          clearText = encryptionService.decrypt(encrypted);
81          assertTrue(clearText.equals(valueToHide));
82  
83      }
84  
85      /**
86       * Verfies that the DemonstrationGradeEncryptionServiceImpl is thread-safe. We had problems originally with the thread-safety of the
87       * implementation so we added this test to verify and prevent regression.
88       */
89      // method copied from KEW where it was originally testing DESEncryptionService class
90      public void testEncryptionMultiThreaded() throws Exception {
91          String key = DemonstrationGradeEncryptionServiceImpl.generateEncodedKey();
92          Config config = ConfigContext.getCurrentContextConfig();
93          if (config == null) {
94              // because of previously running tests, the config might already be initialized
95              config = new JAXBConfigImpl();
96              ConfigContext.init(config);
97          }
98          config.putProperty("encryption.key", key);
99  
100         final EncryptionService service = new DemonstrationGradeEncryptionServiceImpl();
101         List<Thread> threads = new ArrayList<Thread>();
102         failed = false;
103         for (int i = 0; i < 10; i++) {
104             threads.add(new Thread() {
105                 public void run() {
106                     try {
107                         for (int j = 0; j < 100; j++) {
108                             String badText = "This is so going to no longer explode";
109                             String badEnc = service.encrypt(badText);
110                             String badDec = service.decrypt(badEnc);
111                             assertEquals(badText, badDec);
112                         }
113                     } catch (Exception e) {
114                         e.printStackTrace();
115                         failed = true;
116                         fail("Encryption service use to be non-thread safe, but it should be now!");
117                     }
118                 }
119             });
120         }
121         for (Thread thread : threads) {
122             thread.start();
123         }
124         for (Thread thread : threads) {
125             thread.join();
126         }
127         // assert that the encryption doesn't fail any longer in a multi-threaded environment, this verifies
128         // the fix to the encryption service
129         assertFalse(failed);
130     }
131 
132     /**
133      * Similar to the test above except that a new DemonstrationGradeEncryptionServiceImpl is created for each thread.
134      */
135     // method copied from KEW where it was originally testing DESEncryptionService class
136     public void testEncryptionMultiThreadedSafe() throws Exception {
137         String key = DemonstrationGradeEncryptionServiceImpl.generateEncodedKey();
138         Config config = ConfigContext.getCurrentContextConfig();
139         if (config == null) {
140             // because of previously running tests, the config might already be initialized
141             config = new JAXBConfigImpl();
142             ConfigContext.init(config);
143         }
144         config.putProperty("encryption.key", key);
145         List<Thread> threads = new ArrayList<Thread>();
146         failed = false;
147         for (int i = 0; i < 10; i++) {
148             threads.add(new Thread() {
149                 public void run() {
150                     try {
151                         final EncryptionService service = new DemonstrationGradeEncryptionServiceImpl();
152                         for (int j = 0; j < 100; j++) {
153                             String badText = "This is so going to NOT explode";
154                             String badEnc = service.encrypt(badText);
155                             String badDec = service.decrypt(badEnc);
156                             assertEquals(badText, badDec);
157                         }
158                     } catch (Exception e) {
159                         e.printStackTrace();
160                         e.printStackTrace();
161                         failed = true;
162                         fail("Encryption service failed in mysterious ways.");
163                     }
164                 }
165             });
166         }
167         for (Thread thread : threads) {
168             thread.start();
169         }
170         for (Thread thread : threads) {
171             thread.join();
172         }
173         // assert that the encryption/decription did not fail
174         assertFalse(failed);
175     }
176 }