字符串加密解密处理

    使用场景中需要对字符串加密、解密,且加解密可以指定密钥时,可以使用javax.crypto.Cipher类作为加解密工具,java.security.Key作为密钥。

方法一:

  1. 加密时先将字符串转换成byte数组,用Cipher.doFinal加密后获取加密byte数组,并转换成16进制字符串作为加密结果
  2. 解密时将需要解密的16进制字符串转换成加密后的byte数组,再用Cipher.doFinal解密,用解密后的byte数组创建String对象获得解密后字符串。

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;

public class EncryptUtils {

    private static String defaultKey = "youngsun";

    //加密工具
    private Cipher encryptCipher;
    //解密工具
    private Cipher decryptCipher;

    /**
     * 指定密钥构造方法
     * @param keyStr 传入的密钥
     * @throws Exception
     */
    public EncryptUtils(String keyStr) throws Exception {
        Key key = getKey(keyStr.getBytes());
        encryptCipher = Cipher.getInstance("DES");
        encryptCipher.init(Cipher.ENCRYPT_MODE, key);
        decryptCipher = Cipher.getInstance("DES");
        decryptCipher.init(Cipher.DECRYPT_MODE, key);
    }

    /** 默认密钥构造方法 */
    public EncryptUtils() throws Exception {
        this(defaultKey);
    }

    /**
     * byte数组转化成16进制字符串(与hexStr2ByteArr互为转换)
     * @param byteArr
     * @return hexStr
     */
    public static String byteArr2HexStr(byte[] byteArr) throws Exception {
        int arrLen = byteArr.length;
        //byte转16进制需要预留两位,不到两位的用0补充
        StringBuffer sb = new StringBuffer(arrLen*2);
        for (int i = 0; i < arrLen; i++) {
            int b = byteArr[i];
            while (b < 0) {
                b = b + 256;
            }
            if(b < 16){
                sb.append("0");
            }
            String s = Integer.toString(b, 16);
            sb.append(s);
        }
        return sb.toString();
    }

    /**
     * 16进制字符串转换成byte数组(与byteArr2HexStr互为转换)
     * @param hexStr
     * @return byte[]
     */
    public static byte[] hexStr2ByteArr(String hexStr){
        int strLen = hexStr.length();
        byte[] bytes = new byte[strLen / 2];

        for (int i = 0; i < strLen; i = i + 2) {
            String byteStr = hexStr.substring(i, i + 2);
            bytes[i/2] = (byte)Integer.parseInt(byteStr, 16);
        }
        return bytes;
    }

    /**
     * byte数组加密
     * @param bytes 待加密byte数组
     * @return encryptBytes 加密后数组
     * @throws Exception
     */
    public byte[] encryptBytes(byte[] bytes) throws Exception{
        byte[] encryptBytes = encryptCipher.doFinal(bytes);
        return encryptBytes;
    }

    /**
     * 字符串加密
     * @param str 待加密字符串
     * @return
     * @throws Exception
     */
    public String encryptStr(String str) throws Exception{
        byte[] bytes = str.getBytes();
        byte[] encryptBytes = encryptCipher.doFinal(bytes);
        String encryptStr = byteArr2HexStr(encryptBytes);
        return encryptStr;
    }

    public byte[] decryptBytes(byte[] bytes) throws Exception{
       return decryptCipher.doFinal(bytes);
    }

    public String decryptString(String str) throws Exception{
        byte[] bytes = decryptBytes(hexStr2ByteArr(str));
        return new String(bytes);
    }

    /**
     *  创建密钥需要数组长度为8位,不足8位的用0替代,超出8位取前八位
     * @param keyBytes 密钥字符串转数组,获取Key
     * @return Key
     */
    private Key getKey(byte[] keyBytes){
        byte[] entBytes = new byte[8];
        for (int i = 0; i < keyBytes.length && i < entBytes.length; i++) {
            entBytes[i] = keyBytes[i];//keyBytes不足8位时,余下
        }
        Key key = new SecretKeySpec(entBytes, "DES");
        return key;
    }

}

方法二:

    基于方法一,将上面代码中的byte数组与16进制字符串互转部分改为由com.thoughtworks.xstream.core.util.Base64Encoder类加密解密处理。

因为如果加密后的byte数组,直接用于创建String对象作为加密字符串的转换不可逆(再将字符串转换成byte数组后的结果与加密结果byte数组不一致)。


        @Test
	    public void testEncryptUtils(){
		String testStr = "123456";
		String keyStr = "youngsun";
		try {
			Key key = new SecretKeySpec(keyStr.getBytes(), "DES");
			Cipher encryptCipher = Cipher.getInstance("DES");
			encryptCipher.init(Cipher.ENCRYPT_MODE, key);
			Cipher decryptCipher = Cipher.getInstance("DES");
			decryptCipher.init(Cipher.DECRYPT_MODE, key);

			System.out.println("加密前:" + testStr);
			byte[] bytes = encryptCipher.doFinal(testStr.getBytes());
			System.out.println("加密后数组bytes:" + Arrays.toString(bytes));
			String byteStr = new String(bytes);
			System.out.println("bytes转换成字符串 byteStr:" + byteStr);
			System.out.println("byteStr转换byte数组" +              Arrays.toString(byteStr.getBytes()));
			Base64Encoder base64Encoder = new Base64Encoder();
			String s = base64Encoder.encode(bytes);
			System.out.println("加密后:" + s);
			byte[] bytes2 = base64Encoder.decode(s);
			byte[] bytes1 = decryptCipher.doFinal(bytes2);
			System.out.println("解密后:" + new String(bytes1) );
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		}catch (InvalidKeyException e) {
			e.printStackTrace();
		}catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
}

运行结果:

加密前:123456
加密后数组bytes:[58, -67, 118, 96, 3, -74, -109, 5]
bytes转换成字符串 byteStr::�v`��
byteStr转换byte数组[58, -17, -65, -67, 118, 96, 3, -17, -65, -67, -17, -65, -67, 5]
加密后:Or12YAO2kwU=
解密后:123456

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值