欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java加解密

程序员文章站 2024-03-14 17:40:22
...

1. 算法

1.1 AES

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public final class Encrypt {

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    public static final String UTF_8 = "UTF-8";

    /**
     * 加密
     * 
     * @param by
     *            加密内容
     * @param ivStr
     *            加密iv,包括秘钥和盐值,中间用逗号分隔
     * @return 密文
     */
    public static byte[] encrypt(byte[] by, String ivStr) {

        try {
            String[] ivs = ivStr.split(",");
            SecretKeySpec skeySpec = getKey(ivs[0]); // 秘钥
            IvParameterSpec iv = new IvParameterSpec(ivs[1].getBytes(UTF_8)); // 盐值
            Cipher encryptCipher = Cipher.getInstance(ALGORITHM);
            encryptCipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = encryptCipher.doFinal(by);
            return encrypted;
        } catch (Exception e) {
            System.out.println("encrypt exception: " + e);
        }
        return null;
    }

    /**
     * 解密
     * 
     * @param by
     *            密文
     * @param ivStr
     *            解密iv,包括秘钥和盐值,中间用逗号分隔
     * @return 明文
     */
    public static byte[] decrypt(byte[] by, String ivStr) {
        try {
            String[] ivs = ivStr.split(",");
            SecretKeySpec skeySpec = getKey(ivs[0]); // 秘钥
            IvParameterSpec iv = new IvParameterSpec(ivs[1].getBytes(UTF_8)); // 盐值
            Cipher decryptCipher = Cipher.getInstance(ALGORITHM);
            decryptCipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            if (by != null) {
                byte[] original = decryptCipher.doFinal(by);
                return original;
            }
        } catch (Exception e) {
            System.out.println("decrypt exception: " + e);
        }
        return null;
    }

    private static SecretKeySpec getKey(String strKey) throws UnsupportedEncodingException {
        byte[] arrBTmp = strKey.getBytes(UTF_8);

        byte[] arrB = new byte[16];

        int length = arrBTmp.length < arrB.length ? arrBTmp.length : arrB.length;

        System.arraycopy(arrBTmp, 0, arrB, 0, length);

        SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES");

        return skeySpec;
    }

    /**
     * 将二进制转换成16进制
     *
     * @param buf
     *            byte
     * @return String
     */
    private static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 生成指定位数的随机字符串
     *
     * @param count
     *            生成字符串位数为count*2
     * @return 安全随机字符串
     */
    public static String getRandom(int count) {
        SecureRandom random = null;
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException e) {
            System.out.println("getRandom exception: " + e);
        }
        byte[] salt = new byte[count];
        random.nextBytes(salt);
        return parseByte2HexStr(salt);
    }

    public static void main(String[] args) throws Exception {
        String ivKey = Encrypt.getRandom(16 / 2) + "," + Encrypt.getRandom(16 / 2);
        // 对文本加解密
        String content = "Hello world";
        byte[] secret = Encrypt.encrypt(content.getBytes(Encrypt.UTF_8), ivKey); // 加密
        System.out.println(new String(Encrypt.decrypt(secret, ivKey), Encrypt.UTF_8)); // 解密

        // 对文件加解密
        // (1) 打开文件流以字节方式读入,然后加密,最后写入文件
        // (2) 打开文件流以字节方式读入,然后解密,最后写入文件
        File src = new File("d:\\abc.txt");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
        byte[] buf = new byte[(int) src.length()];
        bis.read(buf);
        bis.close();
        byte[] ds = Encrypt.encrypt(buf, ivKey); // 加密

        byte[] out = Encrypt.decrypt(ds, ivKey); // 解密
        File dst = new File("d:\\cba.txt"); // 解密之后的文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dst));
        bos.write(out);
        bos.close();
        System.out.println("test finished...");

    }

}