/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.wicket.util.crypt; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.apache.wicket.util.lang.Args; /** * Provide some simple means to encrypt and decrypt strings such as passwords. The whole * implementation is based around Sun's security providers and uses the <a * href="http://www.ietf.org/rfc/rfc2898.txt">PBEWithMD5AndDES</a> method to encrypt and decrypt the * data. * * @author Juergen Donnerstag */ public class SunJceCrypt extends AbstractCrypt { /** * Iteration count used in combination with the salt to create the encryption key. */ private final static int COUNT = 17; /** Name of the default encryption method */ public static final String DEFAULT_CRYPT_METHOD = "PBEWithMD5AndDES"; /** Salt */ public final static byte[] SALT = { (byte)0x15, (byte)0x8c, (byte)0xa3, (byte)0x4a, (byte)0x66, (byte)0x51, (byte)0x2a, (byte)0xbc }; private static final PBEParameterSpec PARAMETER_SPEC = new PBEParameterSpec(SALT, COUNT); /** The name of encryption method (cipher) */ private final String cryptMethod; /** * Constructor */ public SunJceCrypt() { this(DEFAULT_CRYPT_METHOD); } /** * Constructor that uses a custom encryption method (cipher). * You may need to override {@link #createKeySpec()} and/or * {@link #createParameterSpec()} for the custom cipher. * * @param cryptMethod * the name of encryption method (the cipher) */ public SunJceCrypt(String cryptMethod) { this.cryptMethod = Args.notNull(cryptMethod, "Crypt method"); } /** * Crypts the given byte array * * @param input * byte array to be encrypted * @param mode * crypt mode * @return the input crypted. Null in case of an error * @throws GeneralSecurityException */ @Override protected byte[] crypt(final byte[] input, final int mode) throws GeneralSecurityException { SecretKey key = generateSecretKey(); AlgorithmParameterSpec spec = createParameterSpec(); Cipher ciph = createCipher(key, spec, mode); return ciph.doFinal(input); } /** * Creates the {@link javax.crypto.Cipher} that will do the de-/encryption. * * @param key * the secret key to use * @param spec * the parameters spec to use * @param mode * the mode ({@link javax.crypto.Cipher#ENCRYPT_MODE} or {@link javax.crypto.Cipher#DECRYPT_MODE}) * @return the cipher that will do the de-/encryption * @throws GeneralSecurityException */ protected Cipher createCipher(SecretKey key, AlgorithmParameterSpec spec, int mode) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance(cryptMethod); cipher.init(mode, key, spec); return cipher; } /** * Generate the de-/encryption key. * <p> * Note: if you don't provide your own encryption key, the implementation will use a default. Be * aware that this is potential security risk. Thus make sure you always provide your own one. * * @return secretKey the security key generated * @throws NoSuchAlgorithmException * unable to find encryption algorithm specified * @throws InvalidKeySpecException * invalid encryption key */ protected SecretKey generateSecretKey() throws NoSuchAlgorithmException, InvalidKeySpecException { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(cryptMethod); KeySpec spec = createKeySpec(); return keyFactory.generateSecret(spec); } /** * @return the parameter spec to be used for the configured crypt method */ protected AlgorithmParameterSpec createParameterSpec() { return PARAMETER_SPEC; } /** * @return the key spec to be used for the configured crypt method */ protected KeySpec createKeySpec() { return new PBEKeySpec(getKey().toCharArray()); } }