All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hframework.common.util.security.SecurityUtils Maven / Gradle / Ivy

There is a newer version: 1.0.2
Show newest version
//***************************************************************************
/**
 * @类名称:Security.java
 * @处理内容:安全相关(加密/解密)
 */
// ***************************************************************************
package com.hframework.common.util.security;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SecurityUtils {

    public static final String ALGORITHM_DES = "DESede";

    public static final String ALGORITHM_SHA1 = "SHA-1";

    public static final String ALGORITHM_MD5 = "MD5";

    /**
     * 静态成员初始化,BASE64编码表
     */
    final private static String encodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * BASE64编码器,编码算法如下: 1.将数据按3个字节一组分成数块; 2.每块将3个8位的数据转换成4个6位数据段; 11111111
     * 00000000 11111111 ---- 111111 110000 000011 111111 12345678 12345678
     * 12345678 ---- 123456 781234 567812 345678 3.根据Base64字符表得到4个6位数据段对应的字符;
     * 4.如果最后一块只有两个字节,则添加两个0位,转换成对应Base64字符表的三个字符,并在结尾添一个'='字符;
     * 如果最后一块只有一个字节,则添加四个0位,转换成对应Base64字符表的两个字符,并在结尾添两个'='字符。
     *
     * @param data 需要编码的数据
     * @return 返回编码后结果
     */
    public static String BASE64Encode(byte[] data) {
        // 判断输入数据的有效性
        if (data == null) {
            return null;
        }
        // 声明保存结构的缓冲区
        StringBuffer encoded = new StringBuffer();
        // 循环开始编码
        int i, individual, remain = 0;
        for (i = 0; i < data.length; i++) {
            // 把BYTE数据类型转换成int
            individual = data[i] & 0x000000ff;
            switch (i % 3) {
                case 0:
                    // 保存编码数据
                    encoded.append(encodeTable.charAt(individual >> 2));
                    // 保留需移动的位
                    remain = (individual << 4) & 0x30;
                    break;
                case 1:
                    // 保存编码数据
                    encoded.append(encodeTable.charAt(remain | individual >> 4));
                    // 保留需移动的位
                    remain = (individual << 2) & 0x3c;
                    break;
                case 2:
                    // 保存编码数据
                    encoded.append(encodeTable.charAt(remain | individual >> 6));
                    // 保存编码数据
                    encoded.append(encodeTable.charAt(individual & 0x3f));
                    break;
            }
            // 判断换行
            if (((i + 1) % 57) == 0)
                encoded.append("\r\n");
        }
        // 末尾补位
        switch (i % 3) {
            case 1:
                // 补四个0位,生成两个Base64字符,末尾加==
                encoded.append(encodeTable.charAt(remain));
                encoded.append("==");
                break;
            case 2:
                // 补两个0位,生成三个Base64字符,末尾加=
                encoded.append(encodeTable.charAt(remain));
                encoded.append('=');
                break;
        }
        // 返回结果
        return encoded.toString();
    }

    /**
     * BASE64解码,解码算法如下 1.将数据按4个字节一组分成数块; 2.每块将4个字符去掉最高两位并转换成3个8位的数据段;
     * 注意:数据块中的字符取值不是ASCII集的值,而是Base64字符表中相对应的索引值! 00 111111 00 110000 00 000011
     * 00 111111 ---- 11111111 00000000 11111111 3.根据ASCII字符集得到3个8位数据段对应的字符;
     * 4.如果最后一块只有两个'=',去掉两个'=',并去掉最低两位,转换成对应ASSCII字符集的两个字符;
     * 如果最后一块只有一个'=',去掉'=',并去掉最低四位,转换成对应ASSCII字符集的一个字符。
     *
     * @param encodedData 需要解码的数据
     * @return 解码后的数据
     */
    public static byte[] BASE64Decode(String encodedData) {
        byte[] data = encodedData.getBytes();
        // 分配解码后数据缓冲区
        ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
        // 循环解码,每四个字节分为一个处理数据块
        int nBlockIndex = 0;
        byte individual = 0, remain = 0;
        for (int i = 0; i < data.length; i++) {
            // 过滤回车换行符
            if (data[i] == '\r' || data[i] == '\n')
                continue;
            // 如果到达'=',处理完成
            if (data[i] == '=')
                break;
            // 读取一个块字符
            individual = (byte) decodeBase64Char((char) data[i]);
            // 针对在块的不同位置,分别处理
            switch ((nBlockIndex++) % 4) {
                case 0:
                    remain = (byte) (individual << 2);
                    break;
                case 1:
                    output.write((char) (remain | (individual >> 4)));
                    remain = (byte) (individual << 4);
                    break;
                case 2:
                    output.write((char) (remain | (individual >> 2)));
                    remain = (byte) (individual << 6);
                    break;
                case 3:
                    output.write(remain | individual);
                    break;
            }
        }
        // 返回解码后结果
        return output.toByteArray();
    }

    /**
     * BASE64字符与其索引反解
     *
     * @param code 编码字符
     * @return 索引
     */
    private static byte decodeBase64Char(char code) {
        if (code >= 'A' && code <= 'Z')
            return (byte) (code - 'A');
        else if (code >= 'a' && code <= 'z')
            return (byte) (code - 'a' + 26);
        else if (code >= '0' && code <= '9')
            return (byte) (code - '0' + 52);
        else if (code == '+')
            return 62;
        else if (code == '/')
            return 63;
        return 64;
    }

    /**
     * 

* 用BASE64对字符串进行加密 *

* * @param str 需要加密的字符串 * @return String 加密后的字符串 */ public static String BASE64EncodeString(String str) { sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder(); return encoder.encodeBuffer(str.getBytes()).trim(); } /** *

* 用BASE64对字符串进行加密 *

* * @param str 需要加密的字符串 * @return String 加密后的字符串 */ public static String BASE64EncodeString(byte[] str) { sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder(); return encoder.encodeBuffer(str).trim(); } /** *

* 对用BASE64加密的字符串进行解密 *

* * @param str 需要解密的字符串 * @return String 解密后的字符串 */ public static String BASE64DecodeString(String str) { sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder(); try { return new String(dec.decodeBuffer(str)); } catch (IOException io) { throw new RuntimeException(io.getMessage(), io.getCause()); } } /** * 用MD5进行加密 */ public static String MD5DecodeString(String str) { return decodeString(str, ALGORITHM_MD5); } /** * 用SHA进行加密 */ public static String SHADecodeString(String str) { return decodeString(str, ALGORITHM_SHA1); } /** * 用MD5进行加密 */ public static byte[] MD5DecodeByte(byte[] str) { return decodeByte(str, ALGORITHM_MD5); } /** * 用SHA进行加密 */ public static byte[] SHADecodeByte(byte[] str) { return decodeByte(str, ALGORITHM_SHA1); } private static String decodeString(String str, String method) { MessageDigest md = null; String dstr = null; try { // 生成一个MD5加密计算摘要 md = MessageDigest.getInstance(method); md.update(str.getBytes()); // digest()最后确定返回md5 hash值,返回值为8为字符串。 // 因为md5 hash值是16位的hex值,实际上就是8位的字符 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 dstr = new BigInteger(1, md.digest()).toString(16); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return dstr; } private static byte[] decodeByte(byte[] strSrc, String method) { byte[] returnByte = null; MessageDigest md = null; try { // 生成一个MD5加密计算摘要 md = MessageDigest.getInstance(method); md.update(strSrc); // digest()最后确定返回md5 hash值,返回值为8为字符串。 // 因为md5 hash值是16位的hex值,实际上就是8位的字符 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 byte[] e = md.digest(); // 接口定义中密钥长度为24位,补0 returnByte = new byte[24]; int i = 0; while (i < e.length && i < 24) { returnByte[i] = e[i]; i++; } if (i < 24) { returnByte[i] = 0; i++; } } catch (Exception e) { e.printStackTrace(); } return returnByte; } /** * 用3DES算法进行加密 * @param str 源字符串 * @param strKey 密钥字符串 * @return */ public static byte[] encode3DES(String str, String strKey) { try { byte[] byteKey = strKey.getBytes().length == 24 ? strKey.getBytes() : build3DesKey(strKey); SecretKey desKey = new SecretKeySpec(byteKey, ALGORITHM_DES); //生成密钥 Cipher cipher = Cipher.getInstance(ALGORITHM_DES); cipher.init(Cipher.ENCRYPT_MODE, desKey); return cipher.doFinal(str.getBytes()); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 用3DES算法进行解密 * @param bytes 源二进制数组 * @param strKey 密钥字符串 * @return */ public static byte[] decode3DES(byte[] bytes, String strKey) { try { byte[] byteKey = strKey.getBytes().length == 24 ? strKey.getBytes() : build3DesKey(strKey); SecretKey desKey = new SecretKeySpec(byteKey, ALGORITHM_DES); //生成密钥 Cipher cipher = Cipher.getInstance(ALGORITHM_DES); cipher.init(Cipher.DECRYPT_MODE, desKey); return cipher.doFinal(bytes); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 根据字符串生成密钥字节数组 * * @param keyStr 密钥字符串 * @return * @throws UnsupportedEncodingException */ public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException { byte[] key = new byte[24]; //声明一个24位的字节数组,默认里面都是0 byte[] temp = keyStr.getBytes(); //将字符串转成字节数组 //执行数组拷贝 System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位) if (key.length > temp.length) { //如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中 System.arraycopy(temp, 0, key, 0, temp.length); } else { //如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中 System.arraycopy(temp, 0, key, 0, key.length); } return key; } public static void main(String[] args) throws Exception { //vxmMRYptCNU= //Hello String key = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"; String msg = "3DES加密解密案例"; //加密 byte[] secretArr = SecurityUtils.encode3DES(msg, key); String temp = SecurityUtils.BASE64Encode(secretArr); System.out.println("【加密后】:" + temp); //解密 byte[] myMsgArr = SecurityUtils.decode3DES("vxmMRYptCNU".getBytes(), key); System.out.println("【解密后】:" + new String(myMsgArr)); } public static String getMD5(String sourceStr, int length) { String result = ""; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(sourceStr.getBytes()); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) i += 256; if (i < 16) buf.append("0"); buf.append(Integer.toHexString(i)); } if (length == 32){ result = buf.toString(); }else { result = buf.toString().substring(8, 24); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy