⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bytearrayguard.java

📁 一个比较好的jsf spring hibernate的例子
💻 JAVA
字号:
/* * $Id: ByteArrayGuard.java,v 1.4 2007/04/27 22:00:40 ofung Exp $ *//* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. *  * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. *  * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License").  You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific * language governing permissions and limitations under the License. *  * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code.  If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" *  * Contributor(s): *  * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license."  If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above.  However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */package renderkits.util;import javax.crypto.Cipher;import javax.crypto.Mac;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESedeKeySpec;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import javax.faces.context.FacesContext;import java.security.Key;import java.security.MessageDigest;import java.security.SecureRandom;import java.util.Arrays;import java.util.Map;import java.util.logging.Level;import java.util.logging.Logger;/** * This utility class provides services to encrypt or decrypt a byte array. * The algorithm used to encrypt byte array is 3DES with CBC * The algorithm used to create the message authentication code (MAC) is SHA1 * <p/> * Original author Inderjeet Singh, J2EE Blue Prints Team. Modified to suit JSF * needs. */public class ByteArrayGuard {    public static final int DEFAULT_KEY_LENGTH = 24;    public static final int DEFAULT_MAC_LENGTH = 20;    public static final int DEFAULT_IV_LENGTH = 8;    public static final String SESSION_KEY_FOR_PASSWORD =          "com.sun.faces.clientside-state.password-key";    public static final int DEFAULT_PASSWORD_LENGTH = 24;    // Log instance for this class    private static Logger logger;    static {        logger = Util.getLogger(Util.FACES_LOGGER);    }    /**     * @param ps the password strategy to create password for encryption and decryption     *           uses default values for the length of the encryption key, MAC key, and     *           the initialization vector     *     * @see DEFAULT_KEY_LENGTH     * @see DEFAULT_MAC_LENGTH     * @see DEFAULT_IV_LENGTH     */    public ByteArrayGuard() {        this(DEFAULT_KEY_LENGTH, DEFAULT_MAC_LENGTH, DEFAULT_IV_LENGTH);    }    /**     * @param keyLength the length of the key used for encryption     * @param macLength the length of the message authentication used     * @param ivLength  length of the initialization vector used by the block cipher     * @param     */    public ByteArrayGuard(int keyLength, int macLength, int ivLength) {        this.keyLength = keyLength;        this.macLength = macLength;        this.ivLength = ivLength;    }    /**     * Encrypts the specified plaindata using the specified password. It also     * stores the MAC and the IV in the output. The 20-byte MAC is stored     * first, followed by the 8-byte IV, followed by the encrypted     * contents of the file.     *     * @param context   FacesContext for this request     * @param plaindata The plain text that needs to be encrypted     *     * @return The encrypted contents     */    public byte[] encrypt(FacesContext context, byte[] plaindata) {        try {            // generate a key that can be used for encryption from the             // supplied password            byte[] rawKey =                  convertPasswordToKey(getPasswordToSecureState(context));            // choose block encryption algorithm            Cipher cipher = getBlockCipherForEncryption(rawKey);            // encrypt the plaintext            byte[] encdata = cipher.doFinal(plaindata);            // choose mac algorithm            Mac mac = getMac(rawKey);            // generate MAC for the initialization vector of the cipher            byte[] iv = cipher.getIV();            mac.update(iv);            // generate MAC for the encrypted data            mac.update(encdata);            // generate MAC            byte[] macBytes = mac.doFinal();            // concat byte arrays for MAC, IV, and encrypted data            // Note that the order is important here. MAC and IV are            // of fixed length and need to appear before the encrypted data            // for easy extraction while decrypting.            byte[] tmp = concatBytes(macBytes, iv);            byte[] securedata = concatBytes(tmp, encdata);            return securedata;        } catch (Exception e) {            if (logger.isLoggable(Level.SEVERE)) {                logger.log(Level.SEVERE, e.getMessage(), e.getCause());            }            throw new RuntimeException(e);        }    }    /**     * Decrypts the specified byte array using the specified password, and     * generates an inputstream from it. The file must be encrypted by the     * above method for encryption. The method also verifies the MAC. It     * uses the IV present in the file for decryption.     *     * @param context    Faces Context for this request     * @param securedata The encrypted data (including mac and initialization     *                   vector) that needs to be decrypted     *     * @return A byte array containing the decrypted contents     */    public byte[] decrypt(FacesContext context, byte[] securedata) {        try {            // Extract MAC            byte[] macBytes = new byte[macLength];            System.arraycopy(securedata, 0, macBytes, 0, macBytes.length);            // Extract initialization vector used for encryption            byte[] iv = new byte[ivLength];            System.arraycopy(securedata, macBytes.length, iv, 0, iv.length);            // Extract encrypted data            byte[] encdata =                  new byte[securedata.length - macBytes.length - iv.length];            System.arraycopy(securedata,                             macBytes.length + iv.length,                             encdata,                             0,                             encdata.length);            // verify MAC by regenerating it and comparing it with the received value            byte[] rawKey =                  convertPasswordToKey(getPasswordToSecureState(context));            Mac mac = getMac(rawKey);            mac.update(iv);            mac.update(encdata);            byte[] macBytesCalculated = mac.doFinal();            if (Arrays.equals(macBytes, macBytesCalculated)) {                // decrypt data only if the MAC was valid                Cipher cipher = getBlockCipherForDecryption(rawKey, iv);                byte[] plaindata = cipher.doFinal(encdata);                return plaindata;            } else {                if (logger.isLoggable(Level.WARNING)) {                    // PENDING (visvan) localize                    logger.warning("ERROR: MAC did not verify!");                }                return null;            }        } catch (Exception e) {            if (logger.isLoggable(Level.SEVERE)) {                logger.log(Level.SEVERE, e.getMessage(), e.getCause());            }            throw new RuntimeException(e);        }    }    /**     * This method provides a password to be used for encryption/decryption of     * client-side state.     */    private String getPasswordToSecureState(FacesContext context) {        Map sessionMap = context.getExternalContext().getSessionMap();        if (sessionMap == null) {            // Setting it to an arbitrary value. As long as the same value is used            // by both serializer and deserializer, the encryption will work.             // However, the encryption will be useless since this arbitrary             // value can be guessed by an attacker.            // PENDING (visvan) localize            if (logger.isLoggable(Level.WARNING)) {                logger.warning(                      "Key to retrieve password from session could not " +                      "be found. Using default value. This will enable " +                      "the encryption and decryption to work, but the " +                      "client-side state saving method is NO longer secure.");            }            password = "easy-to-guess-password";        } else {            password = (String) sessionMap.get(SESSION_KEY_FOR_PASSWORD);            if (password == null) {                password = (String)                      ByteArrayGuard.getRandomString(DEFAULT_PASSWORD_LENGTH);                sessionMap.put(SESSION_KEY_FOR_PASSWORD, password);            }        }        return password;    }    /**     * This method converts the specified password into a key in a     * deterministic manner. The key is then usable for creating ciphers     * and MACs.     *     * @return a byte array containing a key based on the specified     *         password. The length of the returned byte array is KEY_LENGTH.     */    private byte[] convertPasswordToKey(byte[] password) {        try {            MessageDigest md = MessageDigest.getInstance("SHA");            byte[] seed = md.digest(password);            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");            random.setSeed(seed);            byte[] rawkey = new byte[keyLength];            random.nextBytes(rawkey);            return rawkey;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    /**     * A convenience alias to the above method which takes a string as     * the password.     */    private byte[] convertPasswordToKey(String password) {        return convertPasswordToKey(password.getBytes());    }    /**     * @param rawKey must be 24 bytes in length.     *     * @return a 3DES block cipher to be used for encryption based on the     *         specified key     */    private Cipher getBlockCipherForEncryption(byte[] rawKey) {        try {            SecretKeyFactory keygen = SecretKeyFactory.getInstance("DESede");            DESedeKeySpec keyspec = new DESedeKeySpec(rawKey);            Key key = keygen.generateSecret(keyspec);            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");            byte[] iv = new byte[ivLength];            getPRNG().nextBytes(iv);            IvParameterSpec ivspec = new IvParameterSpec(iv);            cipher.init(Cipher.ENCRYPT_MODE, key, ivspec, getPRNG());            return cipher;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private static Cipher getBlockCipherForDecryption(byte[] rawKey, byte[]          iv) {        try {            SecretKeyFactory keygen = SecretKeyFactory.getInstance("DESede");            DESedeKeySpec keyspec = new DESedeKeySpec(rawKey);            Key key = keygen.generateSecret(keyspec);            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");            IvParameterSpec ivspec = new IvParameterSpec(iv);            cipher.init(Cipher.DECRYPT_MODE, key, ivspec, getPRNG());            return cipher;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private Mac getMac(byte[] rawKey) {        try {            Mac mac = Mac.getInstance("HmacSHA1");            SecretKeySpec key =                  new SecretKeySpec(rawKey, 0, macLength, "HmacSHA1");            mac.init(key);            return mac;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    /**     * Generates a cryptographically random string     *     * @param size the desired length of the string     */    static String getRandomString(int size) {        byte[] data = new byte[size];        getPRNG().nextBytes(data);        return new String(data);    }    private static int getRandomInt() {        byte[] data = new byte[4];        getPRNG().nextBytes(data);        return data[0] + data[1] * 256 + data[2] * 65536 + data[3] * 16777216;    }    private static SecureRandom getPRNG() {        try {            if (prng == null) {                prng = SecureRandom.getInstance("SHA1PRNG");            }            return prng;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private static String getHexString(byte[] b) {        StringBuffer buf = new StringBuffer(b.length);        for (int i = 0; i < b.length; ++i) {            byte2hex(b[i], buf);        }        return buf.toString();    }    /**     * This method concatenates two byte arrays     *     * @param array1 first byte array to be concatenated     * @param array2 second byte array to be concatenated     *     * @return a byte array of array1||array2     */    private static byte[] concatBytes(byte[] array1, byte[] array2) {        byte[] cBytes = new byte[array1.length + array2.length];        try {            System.arraycopy(array1, 0, cBytes, 0, array1.length);            System.arraycopy(array2, 0, cBytes, array1.length, array2.length);        } catch (Exception e) {            throw new RuntimeException(e);        }        return cBytes;    }    /** Converts a byte to hex digit and writes to the supplied buffer */    private static void byte2hex(byte b, StringBuffer buf) {        char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',                           'A', 'B', 'C', 'D', 'E', 'F'};        int high = ((b & 0xf0) >> 4);        int low = (b & 0x0f);        buf.append(hexChars[high]);        buf.append(hexChars[low]);    }    private int keyLength;    private int macLength;    private int ivLength;    private String password = null;    private static SecureRandom prng = null;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -