加密解密RAS+AES。(二)源码及测试代码在文章末尾。

背景
RAS是一个非常好的非对称加密算法。AES则是一个目前国际应用广泛的对称加密算法。这两者优劣皆有,需要结合具体的加密场景,选择不同的加密方式,针对性能和安全,大家需要做出自己的判断。
我们设计了两个工具类,将RAS和AES的一些逻辑封装进去,适合我们在开发时候直接调用。

代码逻辑:

首先是AES算法。

/**
 * AES工具类,密钥必须是16位字符串
 */
public class AESUtils {

首先给他一个随机密钥的方法。

/**
 * 产生随机密钥(这里产生密钥必须是16位)
 */
public static String generateKey() {
    String key = UUID.randomUUID().toString().
    		replace("-", "").substring(0, 16);// 替换掉-号
    return key;
}

这里是加密算法Encrypt。

public static String encryptData(String key, String content) {
    byte[] encryptedBytes = new byte[0];
    try {
    //缺省是ISO-8859-1,content可能是中文,所以这里用UTF-8。
        byte[] byteContent = content.getBytes("UTF-8");
        // 为了与 iOS 统一, 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
        byte[] enCodeFormat = key.getBytes();
        //会把参数放到secretKeySpec的变量Key里,AES会放到algorithm。
        SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
        //取得常量的编码。
        byte[] initParam = IV_STRING.getBytes();
        //把initParam里的字节编码copy到ivParameterSpec的iv字节数组里
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        // 指定加密的算法、工作模式和填充方式
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        //初始化。用密钥和一组算法参数初始化此 Cipher。 
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        //执行
        encryptedBytes = cipher.doFinal(byteContent);
        // 同样对加密后数据进行 base64 编码
        return Base64Utils.encode(encryptedBytes);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

解密的代码这里就不放了。

RAS加密AES密钥。
这是一个测试程序。
加密解密RAS+AES。(二)源码及测试代码在文章末尾。_第1张图片
这个RAEUtils类的加密解密逻辑如下:

public static String encryptByPublicKey(String data) throws Exception {
    byte[] dataByte = data.getBytes();
    byte[] keyBytes = Base64Utils.decode(PUBLIC_KEY);
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    Key key = keyFactory.generatePublic(x509KeySpec);
    // 对数据加密
    // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    /** 得到Cipher对象来实现对源数据的RSA加密 */

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encryptedData = cipher.doFinal(dataByte);
return Base64Utils.encode(encryptedData);

解密方法:

public static String decryptByPrivateKey(String data) throws Exception {
    byte[] encryptedData = Base64Utils.decode(data);
    byte[] keyBytes = Base64Utils.decode(PRIVATE_KEY);
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    //解密
    cipher.init(Cipher.DECRYPT_MODE, privateK);

这是解密代码。

byte[] encryptedData = Base64Utils.decode(data);
byte[] keyBytes = Base64Utils.decode(PRIVATE_KEY);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
    if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
        cache = cipher
                .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
    } else {
        cache = cipher
                .doFinal(encryptedData, offSet, inputLen - offSet);
    }
    out.write(cache, 0, cache.length);
    i++;
    offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData);

因为密文太长,所以要分段解码。

这里用了默认的公钥值,对AES产生的密钥进行加密。先对数据进行编码处理,然后就是用cipher对象对数据进行加密,一些参数的含义,有兴趣的可以查阅JDK文档和JAVAX文档了解。

补充:
AES绝对不要使用 ECB 模式!
https://zh.wikipedia.org/wiki/块密码的工作模式

RSA 1024已经不安全了,起码要2048!

参考文档: https://segmentfault.com/a/1190000015943620
https://github.com/wustrive2008/aes-rsa-java/blob/master/src/main/java/com/wustrive/aesrsa/util/RSA.java

http://tool.oschina.net/uploads/apidocs/jdk-zh/javax/crypto/Cipher.html#init(int, java.security.Key, java.security.spec.AlgorithmParameterSpec)

http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

源码地址: 添加链接描述
有空的,可以star一下,后续源码会更新的。看到问题可以提Issue给我。

你可能感兴趣的:(Java,加密解密)