001: /*
002: * Copyright 2007 The Kuali Foundation
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package edu.iu.uis.eden.security;
017:
018: import java.io.UnsupportedEncodingException;
019: import java.security.GeneralSecurityException;
020:
021: import javax.crypto.Cipher;
022: import javax.crypto.KeyGenerator;
023: import javax.crypto.SecretKey;
024: import javax.crypto.SecretKeyFactory;
025: import javax.crypto.spec.DESKeySpec;
026:
027: import org.apache.commons.codec.binary.Base64;
028: import org.apache.commons.lang.StringUtils;
029: import org.kuali.rice.core.Core;
030:
031: /**
032: * An EncryptionService implementation which encrypts and decrypts values using the DES
033: * encryption algorithm. The secret key used for encryption can be set on this service
034: * or pulled from the "encryption.key" configuration parameter.
035: *
036: * @author Kuali Rice Team (kuali-rice@googlegroups.com)
037: */
038: public class DESEncryptionService implements EncryptionService {
039:
040: public final static String ALGORITHM = "DES/ECB/PKCS5Padding";
041:
042: private final static String CHARSET = "UTF-8";
043:
044: private transient SecretKey desKey;
045:
046: private boolean enabled = false;
047:
048: public DESEncryptionService() throws Exception {
049: if (this .desKey != null) {
050: throw new RuntimeException(
051: "The secret key must be kept secret. Storing it in the Java source code is a really bad idea.");
052: }
053:
054: String key = Core.getCurrentContextConfig().getProperty(
055: "encryption.key");
056:
057: if (!StringUtils.isEmpty(key)) {
058: setSecretKey(key);
059: }
060:
061: }
062:
063: public boolean isEnabled() {
064: return this .enabled;
065: }
066:
067: public String encrypt(Object valueToHide)
068: throws GeneralSecurityException {
069: if (valueToHide == null) {
070: return "";
071: }
072:
073: // Initialize the cipher for encryption
074: Cipher cipher = Cipher.getInstance(ALGORITHM);
075: cipher.init(Cipher.ENCRYPT_MODE, this .desKey);
076:
077: try {
078: // Our cleartext
079: byte[] cleartext = valueToHide.toString().getBytes(CHARSET);
080:
081: // Encrypt the cleartext
082: byte[] ciphertext = cipher.doFinal(cleartext);
083:
084: return new String(Base64.encodeBase64(ciphertext), CHARSET);
085: } catch (Exception e) {
086: throw new RuntimeException(e);
087: }
088: }
089:
090: public String decrypt(String ciphertext)
091: throws GeneralSecurityException {
092: if (StringUtils.isBlank(ciphertext)) {
093: return "";
094: }
095:
096: // Initialize the same cipher for decryption
097: Cipher cipher = Cipher.getInstance(ALGORITHM);
098: cipher.init(Cipher.DECRYPT_MODE, this .desKey);
099:
100: try {
101: // un-Base64 encode the encrypted data
102: byte[] encryptedData = Base64.decodeBase64(ciphertext
103: .getBytes(CHARSET));
104:
105: // Decrypt the ciphertext
106: byte[] cleartext1 = cipher.doFinal(encryptedData);
107:
108: return new String(cleartext1, CHARSET);
109: } catch (UnsupportedEncodingException e) {
110: throw new RuntimeException(e);
111: }
112: }
113:
114: /**
115: *
116: * This method generates keys. This method is implementation specific and
117: * should not be present in any general purpose interface extracted from
118: * this class.
119: *
120: * @return
121: * @throws Exception
122: */
123: public static String generateEncodedKey() throws Exception {
124: KeyGenerator keygen = KeyGenerator.getInstance("DES");
125: SecretKey desKey = keygen.generateKey();
126:
127: // Create the cipher
128: Cipher cipher = Cipher.getInstance(ALGORITHM);
129: cipher.init((Cipher.WRAP_MODE), desKey);
130:
131: SecretKeyFactory desFactory = SecretKeyFactory
132: .getInstance("DES");
133: DESKeySpec desSpec = (DESKeySpec) desFactory.getKeySpec(desKey,
134: javax.crypto.spec.DESKeySpec.class);
135: byte[] rawDesKey = desSpec.getKey();
136:
137: return new String(Base64.encodeBase64(rawDesKey));
138: }
139:
140: private SecretKey unwrapEncodedKey(String key) throws Exception {
141: KeyGenerator keygen = KeyGenerator.getInstance("DES");
142: SecretKey desKey = keygen.generateKey();
143:
144: // Create the cipher
145: Cipher cipher = Cipher.getInstance(ALGORITHM);
146: cipher.init((Cipher.UNWRAP_MODE), desKey);
147:
148: byte[] bytes = Base64.decodeBase64(key.getBytes());
149:
150: SecretKeyFactory desFactory = SecretKeyFactory
151: .getInstance("DES");
152:
153: DESKeySpec keyspec = new DESKeySpec(bytes);
154: SecretKey k = desFactory.generateSecret(keyspec);
155:
156: return k;
157: }
158:
159: /**
160: * Sets the secretKey attribute value.
161: *
162: * @param secretKey
163: * The secretKey to set.
164: * @throws Exception
165: */
166: public void setSecretKey(String secretKey) throws Exception {
167: this .desKey = this .unwrapEncodedKey(secretKey);
168: this .enabled = true;
169: }
170:
171: }
|