对称加密:加密和解密使用同一个密钥。
对称加密算法:DES、3DES、AES等。
DES:数据加密标准,是一种使用密钥加密的块算法;
3DES:DES向AES过渡的加密算法;
AES:高级加密标准,替代DES;
对称加密的特点:
有两种加密模式:ECB、CBC
ECB:电子密码本. 需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。
CBC:密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。
当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则。
NoPadding:不填充;
PKCS5Padding:数据块的大小为8位, 不够就补足;
Base64算法原理:
说明:
/**
* @author:秋一叶
* @date:2020-11-18 9:11
* DES/AES加密解密
*/
public class DesAesDemo {
public static void main(String[] args) throws Exception {
String input = "原文";
//key:DES加密算法的key必须是8个字节
String key = "abcd1234";
//key:AES加密算法的key必须是16个字节
String key2 = "abcdefgh12345678";
//获取Cipher对象的算法,默认加密模式和填充模式为 ECB/PKCS5Padding
String transformation = "DES";
//加密模式为CBC,必须指定初始向量,初始向量中密钥长度必须是8个字节
String transformation1 = "DES/ECB/PKCS5Padding";
//填充模式为NoPadding,原文的长度必须是8字节的整数倍
String transformation2 = "DES/ECB/PKCS5Padding";
//指定加密算法
String algorithm = "DES";
String encryptDES = encryptDES(input, key, transformation, algorithm);
System.out.println("加密后为:" + encryptDES);
String decryptDES = decryptDES(encryptDES, key, transformation, algorithm);
System.out.println("解密后为:" + decryptDES);
}
/**
* 加密
* @param input 原文
* @param key 密钥
* @param transformation 获取Cipher对象的算法
* @param algorithm 获取密钥的算法
* @return
*/
public static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
//获取加密对象
Cipher cipher = Cipher.getInstance(transformation);
//创建加密规则
SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//加密模式为CBC时:初始向量,长度必须是8位
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
//初始化加密模式和算法
cipher.init(Cipher.ENCRYPT_MODE, sks);
//加密
byte[] bytes = cipher.doFinal(input.getBytes());
//对数据进行Base64编码
String encode = Base64.encodeBase64String(bytes);
return new String(encode);
}
/**
* 解密
* @param input
* @param key
* @param transformation
* @param algorithm
* @return
* @throws Exception
*/
public static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
//获取解密对象
Cipher cipher = Cipher.getInstance(transformation);
//指定密钥规则
SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//加密模式为CBC时:初始向量,长度必须是8位
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
//初始化加密模式和算法
cipher.init(Cipher.DECRYPT_MODE, sks);
//对数据进行Base64转码,解密
byte[] bytes = cipher.doFinal(Base64.decodeBase64(input));
return new String(bytes);
}
}
说明:
非对称加密:加密和解密使用一对密钥(公钥和私钥),公钥加密则私钥解密,私钥加密则公钥解密。
非对称加密算法:RSA、ECC等。
非对称加密的特点:
/**
* @author:秋一叶
* @date:2020-11-18 16:01
* 非对称加密RSA
* 综合,先把私钥和公钥保存到本地文件中,再读取出来进行私钥加密,公钥解密
*/
public class RsaDemo03 {
public static void main(String[] args) throws Exception {
String input = "原文";
//generateKeyToFile("RSA", "a.pub", "a.pri");
PrivateKey privateKey = getPrivateKey("a.pri", "RSA");
PublicKey publicKey = getPublicKey("a.pri", "RSA");
//加密
String encrypt = encryptRSA("RSA", privateKey, input);
//解密
String decrypt = decryptRSA("RSA", publicKey, encrypt);
System.out.println("解密后:" + decrypt);
}
/**
* 保存公钥和私钥到本地文件
* @param algorithm 加密算法
* @param pubPath 公钥保存路径
* @param priPath 私钥保存路径
* @throws Exception
*/
private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception{
//创建密钥对生成器对象
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
//生成密钥对
KeyPair keyPair = kpg.generateKeyPair();
//生成私钥和公钥
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
//获取私钥公钥字节数组
byte[] privateKeyEncoded = privateKey.getEncoded();
byte[] publicKeyEncoded = publicKey.getEncoded();
//对公私钥进行base64编码
String privateKeyString = Base64.encodeBase64String(privateKeyEncoded);
String publicKeyString = Base64.encodeBase64String(publicKeyEncoded);
//保存文件
FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
}
/**
* 读取私钥
* @param priPath
* @param algorithm
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String priPath, String algorithm) throws Exception{
//将文件内容转为字符串
String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
//获取密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
//构建密钥规范,进行Base64解码
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
//生成私钥
return keyFactory.generatePrivate(spec);
}
/**
* 读取公钥
* @param pulickPath
* @param algorithm
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String pulickPath,String algorithm) throws Exception{
// 将文件内容转为字符串
String publicKeyString = FileUtils.readFileToString(new File(pulickPath), Charset.defaultCharset());
// 获取密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
// 构建密钥规范 进行Base64解码
X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
// 生成公钥
return keyFactory.generatePublic(spec);
}
/**
* 公钥解密
* @param algorithm 加密算法
* @param key 公钥
* @param encrypted 密文
* @return
* @throws Exception
*/
public static String decryptRSA(String algorithm,Key key,String encrypted) throws Exception{
// 创建加密对象
// 参数表示加密算法
Cipher cipher = Cipher.getInstance(algorithm);
// 私钥进行解密
cipher.init(Cipher.DECRYPT_MODE,key);
// 由于密文进行了Base64编码, 在这里需要进行解码
byte[] decode = Base64.decodeBase64(encrypted);
// 对密文进行解密,不需要使用base64,因为原文不会乱码
byte[] bytes1 = cipher.doFinal(decode);
System.out.println(new String(bytes1));
return new String(bytes1);
}
/**
* 私钥加密
* @param algorithm 加密算法
* @param key 私钥
* @param input 原文
* @return
* @throws Exception
*/
public static String encryptRSA(String algorithm,Key key,String input) throws Exception{
// 创建加密对象
// 参数表示加密算法
Cipher cipher = Cipher.getInstance(algorithm);
// 初始化加密
// 第一个参数:加密的模式
// 第二个参数:使用私钥进行加密
cipher.init(Cipher.ENCRYPT_MODE,key);
// 私钥加密
byte[] bytes = cipher.doFinal(input.getBytes());
// 对密文进行Base64编码
return Base64.encodeBase64String(bytes);
}
}
说明:
常见哈希算法:MD5、SHA-1、SHA-256、SHA-512;
哈希加密函数通常用来做消息摘要;
/**
* @author:秋一叶
* @date:2020-11-18 15:43
* 消息摘要:MD5
*/
public class DigestDemo {
public static void main(String[] args) throws Exception {
String input = "原文";
//获取数字摘要对象
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
//获取数字摘要的字节数组
byte[] digest = messageDigest.digest(input.getBytes());
//System.out.println(Base64.encodeBase64String(digest));
StringBuilder sb = new StringBuilder();
for(byte b : digest){
//转成16进制
String s = Integer.toHexString(b & 0xff);
if(s.length() == 1){
s = "0" + s;
}
sb.append(s);
}
System.out.println(sb.toString());
}
}