加解密

作者: 柚子过来 | 来源:发表于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