AES和3DESC算法进行数据加解密
- AES基本概念
- 3DESC基本概念
- 项目代码
- 代码需要的jar包
- 使用AES算法的CBC模式进行数据加密
- 使用AES算法的CBC模式进行数据解密
- 使用3DESC的ECB模式进行数据加密
- 使用3DESC的ECB模式进行数据解密
- 其他说明
AES基本概念
三个基本的概念:密钥、填充、模式。
密钥:密钥是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。AES支持三种长度的密钥:128位,192位,256位
填充:NoPadding、PKCS5Padding、PKCS5Padding、ISO10126Padding等。
模式:AES的工作模式,体现在把明文块加密成密文块的处理过程中。AES加密算法提供了五种不同的工作模式:ECB、CBC、CTR、CFB、OFB。(这里使用CBC模式)
3DESC基本概念
3DES是对称加密的一种,是DES向AES过渡的加密算法。它使用三个秘钥的三重DES加密方法,该算法执行三次DES算法,其加密的过程是加密-解密-加密。(这里使用的ECB模式是不需要iv偏移量的)
项目代码
代码需要的jar包
import java.net.URLEncoder;
import java.security.Key;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
使用AES算法的CBC模式进行数据加密
/**
* AES算法的CBC模式数据加密
*
* @param data 需要加密的数据字符串
* @param key 加密使用的key
* @return 加密后的字符串
* @author baitao
* @date 2022/4/17
**/
public String encrypt(String data, String key) {
try{
String enWord = null;
if(null == data|| "".equals(data) || "null".equals(data)) { //判断需要加密的数据字符串不为空
if (null == key|| "".equals(key) || "null".equals(key)){ //判断加密使用的key不为空
if(key.length() != 16) {
System.out.printf("加密使用的key不是16位");
return enWord;
}
byte[] raw = key.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
byte[] ivbyte = "kyipaFrNRe2yLxNM".getBytes("utf-8"); //随机16位字符串
IvParameterSpec iv = new IvParameterSpec(ivbyte);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //使用PKCS5Padding
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
//加密
byte[] encrypted = cipher.doFinal(data.getBytes("utf-8"));
enWord = new BASE64Encoder().encode(encrypted);
return enWord;
}
}
return enWord; //错误返回加密前的数据
} catch (Exception e) {
e.printStackTrace();
System.out.printf("AES数据加密错误", e);
return null;
}
}
使用AES算法的CBC模式进行数据解密
/**
* 数据解密
*
* @param word 需要解密的字符串
* @param key 解密使用的key
* @return 解密后的字符串
* @author baitao
* @date 2022/4/17
**/
public String decrypt(String word, String key) {
try{
String deData = null;
if(null == data|| "".equals(data) || "null".equals(data)) { //判断需要解密的字符串不为空
if (null == key|| "".equals(key) || "null".equals(key)){ //判断解密使用的key不为空
if(key.length() != 16) {
System.out.printf("加密使用的key不是16位");
return deData;
}
byte[] raw = key.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
byte[] ivbyte = "kyipaFrNRe2yLxNM".getBytes("utf-8"); //随机16位字符串
IvParameterSpec iv = new IvParameterSpec(ivbyte);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //使用PKCS5Padding
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
//解密
byte[] decrypted = new BASE64Decoder().decodeBuffer(word);
byte[] original = cipher.doFinal(decrypted);
deData = new String(original, "utf-8");
return deData;
}
}
return deData; //错误返回解密前的数据
} catch (Exception e) {
e.printStackTrace();
System.out.printf("AES数据解密错误", e);
return null;
}
}
使用3DESC的ECB模式进行数据加密
/**
* 3desc ecb模式加密
*
* @param data 需要加密的数据字符串
* @param key 加密使用的key
* @return 加密后的字符串
* @author baitao
* @date 2022/4/17
**/
public String encryptDescEcb(String data, String key) {
try{
String enWord = null;
if(null == data|| "".equals(data) || "null".equals(data)) { //判断需要加密的数据字符串不为空
if (null == key|| "".equals(key) || "null".equals(key)){ //判断加密使用的key不为空
DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, securekey);
byte[] b = cipher.doFinal(data.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return URLEncoder.encode(encoder.encode(b), "UTF-8");
}
}
return enWord; //错误返回加密前的数据
} catch (Exception e) {
e.printStackTrace();
System.out.printf("3DESC数据加密错误", e);
return null;
}
}
使用3DESC的ECB模式进行数据解密
/**
* 3desc ecb模式解密
*
* @param word 需要解密的字符串
* @param key 解密使用的key
* @return 解密后的字符串
* @author baitao
* @date 2022/4/17
**/
public String decryptDescEcb(String word, String key) {
try{
String deData = null;
if(null == data|| "".equals(data) || "null".equals(data)) { //判断需要解密的字符串不为空
if (null == key|| "".equals(key) || "null".equals(key)){ //判断解密使用的key不为空
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytesrc = decoder.decodeBuffer(word);
// --解密的key
DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
// --Chipher对象解密
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, securekey);
byte[] retByte = cipher.doFinal(bytesrc);
return new String(retByte, "UTF-8");
}
}
return deData; //错误返回解密前的数据
} catch (Exception e) {
e.printStackTrace();
System.out.printf("3DESC数据解密错误", e);
return null;
}
}
其他说明
1、具体实现时,可能需要对加密、解密前的数据替换换行符等特殊字符,使用data.toString().replace("\n", "")
替换。
2、对于AES使用的key,必须使用16位的字符串,且加解密使用的密钥key需统一。