001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.util.crypt;
018:
019: import java.security.GeneralSecurityException;
020: import java.security.NoSuchAlgorithmException;
021: import java.security.Provider;
022: import java.security.Security;
023: import java.security.spec.InvalidKeySpecException;
024:
025: import javax.crypto.Cipher;
026: import javax.crypto.SecretKey;
027: import javax.crypto.SecretKeyFactory;
028: import javax.crypto.spec.PBEKeySpec;
029: import javax.crypto.spec.PBEParameterSpec;
030:
031: import org.apache.wicket.WicketRuntimeException;
032: import org.apache.wicket.util.lang.Classes;
033:
034: /**
035: * Provide some simple means to encrypt and decrypt strings such as passwords.
036: * The whole implementation is based around Sun's security providers and uses
037: * the <a
038: * href="http://www.semoa.org/docs/api/cdc/standard/pbe/PBEWithMD5AndDES.html">PBEWithMD5AndDES</a>
039: * method to encrypt and decrypt the data.
040: *
041: * @author Juergen Donnerstag
042: */
043: public class SunJceCrypt extends AbstractCrypt {
044: /**
045: * Iteration count used in combination with the salt to create the
046: * encryption key.
047: */
048: private final static int COUNT = 17;
049:
050: /** Name of encryption method */
051: private static final String CRYPT_METHOD = "PBEWithMD5AndDES";
052:
053: /** Salt */
054: private final static byte[] salt = { (byte) 0x15, (byte) 0x8c,
055: (byte) 0xa3, (byte) 0x4a, (byte) 0x66, (byte) 0x51,
056: (byte) 0x2a, (byte) 0xbc };
057:
058: /**
059: * Constructor
060: */
061: public SunJceCrypt() {
062: if (Security.getProviders("Cipher." + CRYPT_METHOD).length > 0) {
063: return; // we are good to go!
064: }
065: try {
066: // Initialize and add a security provider required for encryption
067: final Class clazz = Classes
068: .resolveClass("com.sun.crypto.provider.SunJCE");
069:
070: Security.addProvider((Provider) clazz.newInstance());
071: } catch (IllegalAccessException ex) {
072: throw new WicketRuntimeException(
073: "Unable to load SunJCE service provider", ex);
074: } catch (InstantiationException ex) {
075: throw new WicketRuntimeException(
076: "Unable to load SunJCE service provider", ex);
077: }
078: }
079:
080: /**
081: * Crypts the given byte array
082: *
083: * @param input
084: * byte array to be crypted
085: * @param mode
086: * crypt mode
087: * @return the input crypted. Null in case of an error
088: * @throws GeneralSecurityException
089: */
090: protected final byte[] crypt(final byte[] input, final int mode)
091: throws GeneralSecurityException {
092: SecretKey key = generateSecretKey();
093: PBEParameterSpec spec = new PBEParameterSpec(salt, COUNT);
094: Cipher ciph = Cipher.getInstance(CRYPT_METHOD);
095: ciph.init(mode, key, spec);
096: return ciph.doFinal(input);
097: }
098:
099: /**
100: * Generate the de-/encryption key.
101: * <p>
102: * Note: if you don't provide your own encryption key, the implementation
103: * will use a default. Be aware that this is potential security risk. Thus
104: * make sure you always provide your own one.
105: *
106: * @return secretKey the security key generated
107: * @throws NoSuchAlgorithmException
108: * unable to find encryption algorithm specified
109: * @throws InvalidKeySpecException
110: * invalid encryption key
111: */
112: private final SecretKey generateSecretKey()
113: throws NoSuchAlgorithmException, InvalidKeySpecException {
114: final PBEKeySpec spec = new PBEKeySpec(getKey().toCharArray());
115: return SecretKeyFactory.getInstance(CRYPT_METHOD)
116: .generateSecret(spec);
117: }
118: }
|