加解密

作者: 柚子过来 | 来源:发表于2019-07-19 17:30 被阅读0次

    开发中经常会有字符串加解密的需求,如用户密码加密,可以直接MD5/SHA1加密,MD5/SHA1是不可逆的,验证时可以对输入做MD5/SHA1,然后比较加密后的字符串。但是如果有查询明文密码的需求呢?这就不能使用单向加密的方式了,需要使用双向可逆的加解密,一般常见的有AES/DES/RSA,以下代码展示了一个加解密工具类的实现,使用了Java库中的加密算法实现。
    附: 常见加密算法以及安全性比较 https://www.cnblogs.com/davytitan/p/3850321.html

    package com.cmb.ntms.extconnect.service.utils;
    
    import javax.crypto.*;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.Security;
    
    public class SecurityUtil {
    
    //SecretKey 负责保存对称密钥
    private SecretKey deskey;
    //Cipher负责完成加密或解密工作
    private Cipher cipher;
    
    public SecurityUtil() throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException {
        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(new SecureRandom("defaultSeed".getBytes("UTF-8")));
    
        /*KeyGenerator keygen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed("defaultSeed".getBytes());
        keygen.init(128, random);*/
        deskey = keygen.generateKey();
        cipher = Cipher.getInstance("AES");
    }
    
    /**
     * @param algorithm 加密算法
     * @param seed      种子
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     */
    public SecurityUtil(String algorithm, String seed) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException {
        Security.addProvider(new com.sun.crypto.provider.SunJCE());
        //KeyGenerator 提供对称密钥生成器的功能,支持各种算法
        KeyGenerator keygen = KeyGenerator.getInstance(algorithm);
        keygen.init(new SecureRandom(seed.getBytes("UTF-8")));
        //生成密钥
        deskey = keygen.generateKey();
        //生成Cipher对象,指定其支持的算法
        cipher = Cipher.getInstance(algorithm);
    }
    
    /**
     * 字符串加密
     *
     * @param str
     * @return
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public String encode(String str) throws InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        cipher.init(Cipher.ENCRYPT_MODE, deskey);
        byte[] src = str.getBytes("UTF-8");
        byte[] result = cipher.doFinal(src);
    
        //这里如果直接返回new String(result);再getBytes出来,值是不一样的,所以不直接将字节数组强转成字符串,转换为16进制字符串返回
        //String底层是以Char(2个字节)数组记录的,Byte会转化成Char,因为Char和Byte的长度不同,所以在转化的过程中会对Byte进行整合,主要是用0填充.
        return parseByte2HexStr(result);
    }
    
    /**
     * 对字符串解密
     *
     * @param str
     * @return
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public byte[] decode(String str) throws InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException {
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        //先解出字节数组
        byte[] strBytes = parseHexStr2Byte(str);
        return cipher.doFinal(strBytes);
    }
    
    /**
     * 二进制转16进制字符串
     *
     * @param buf
     * @return
     */
    private String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (byte aBuf : buf) {
            String hex = Integer.toHexString(aBuf & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }
    
    /**
     * 16进制字符串转为二进制字节数组
     *
     * @param hexString
     * @return
     */
    private byte[] parseHexStr2Byte(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (toByte(hexChars[pos]) << 4 | toByte(hexChars[pos + 1]));
        }
        return d;
    }
    
    private static byte toByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
    }
    

    相关文章

      网友评论

          本文标题:加解密

          本文链接:https://www.haomeiwen.com/subject/cnbslctx.html