信息加密算法 分为单向加密,对称加密,非对称加密。
1,单向加密算有MD5和SHA,由单向散列函数实现,输入或者说原始数据称为消息,加密或者散列之后成为散列值.
1.1,特点:
a,只能加密,不能解密。
b,长度固定,同一个消息对应同一个散列值。
c,计算速度较快。
1.2,应用场景:
a, 密码加密。存储密码的散列值,而不是明文密码,只有用户知道自己的密码,散列值相同即表示密码相同。还可以加盐处理。
b,接口验签,使用共享密钥(保密),签名 以共享密钥+业务参数,进行散列运算,接受者以同样的方式加密 比较是否一致。
c,文件完整性校验,下载文件是还有个散列值及其算法,下载下来之后可以通过相同的算法加密该文件,与下载下来的散列值比较,不相同则文件被伪造。
d,云盘秒传。当上传一个文件是,文件服务器会为该文件生成一个散列值,然后到数据库匹配,如果该文件存在,则直接关联记录地址即可。
1.3,JDK的 java.security.MessageDigest 类为我们提供了消息摘要算法,用于 MD5和SHA的散列值生成。
有什么单向加密搞不定的加密场景吗?肯定有,那就是需要还原消息的场景,比如我要加密参数然后传输,之后还需要把参数还原出来,单向加密就没啥用处了,还原不出来。
这个时候需要对称加密和非对称加密出场,
对称加密算法有DES,DES3,AES,对称加密完全依赖密钥,如果密钥丢失则都可以加解密。
非对称加密有 RSA等。两个密钥,公钥加密,私钥解密。耗时较长。
JDK的 javax.crypto.Cipher 这个类为我们提供了对称和非对称加密算法的实现。
基于算法在当前已知攻击方法时密钥的长度和大小,适当的参数选择(如密钥长度)和实现安全性也对安全强度有重大影响。
1,MRD码和同态加密:最新的、基于比较复杂数学问题的加密技术,未知有效攻击手段,认为安全性很高。
2,AES-256:目前最为推荐的对称加密标准,长密钥提供高级别的安全性。
3,ECC:基于椭圆曲线,相对于RSA,提供同等安全级别下更短的密钥,视作安全。
4,RSA:使用足够长的密钥(2048位或以上)时被认为是安全的,但由于潜在的量子计算威胁,安全地位可能在未来受到挑战。
5,SHA-3:最新的安全散列算法,设计的目的是替代SHA-2,为未来的安全威胁做好准备。
6,SHA-256:SHA-2系列中广泛被使用的安全散列算法,被视作安全。
7,3DES:比DES安全,但由于其使用了DES算法,因此对暴力攻击的抵御力较AES弱。
8,SHA-1:由于安全弱点,不再推荐用于安全敏感的环境。
9,MD5:已经被证明对碰撞攻击非常脆弱,被认为是不安全的。
10,DES:因为其短密钥长度而非常容易受到现代暴力攻击的破解,被认为基本不安全。
package com.kuafu.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MessageDigestUtil {
/**
* MD5 加密
*
* @param data 要加密的数据
* @return 32位十六进制字符串
*/
public static String MD5(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* MD5 加密
*
* @param data 要加密的数据
* @return 32位十六进制字符串
*/
public static String MD5(String data) {
return MD5(data.getBytes());
}
/**
* SHA-1 加密
*
* @param data 要加密的数据
* @return 40位十六进制字符串
*/
public static String SHA1(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* SHA-1 加密
*
* @param data 要加密的数据
* @return 40位十六进制字符串
*/
public static String SHA1(String data) {
return SHA1(data.getBytes());
}
/**
* SHA-224 加密
*
* @param data 要加密的数据
* @return 56位十六进制字符串
*/
public static String SHA224(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-224");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* SHA-224 加密
*
* @param data 要加密的数据
* @return 56位十六进制字符串
*/
public static String SHA224(String data) {
return SHA224(data.getBytes());
}
/**
* SHA-256 加密
*
* @param data 要加密的数据
* @return 64位十六进制字符串
*/
public static String SHA256(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* SHA-256 加密
*
* @param data 要加密的数据
* @return 64位十六进制字符串
*/
public static String SHA256(String data) {
return SHA256(data.getBytes());
}
/**
* SHA-384 加密
*
* @param data 要加密的数据
* @return 96位十六进制字符串
*/
public static String SHA384(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-384");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* SHA-384 加密
*
* @param data 要加密的数据
* @return 96位十六进制字符串
*/
public static String SHA384(String data) {
return SHA384(data.getBytes());
}
/**
* SHA-512 加密
*
* @param data 要加密的数据
* @return 128位十六进制字符串
*/
public static String SHA512(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] bytes = md.digest(data);
return bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* SHA-512 加密
*
* @param data 要加密的数据
* @return 128位十六进制字符串
*/
public static String SHA512(String data) {
return SHA512(data.getBytes());
}
/**
* 将字节数组转换为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String bytesToHexString(byte[] bytes) {
StringBuilder hexValue = new StringBuilder();
for (byte b : bytes) {
int val = b & 0xFF;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
public static void main(String[] args) {
System.out.println("MD5\t\t" + MessageDigestUtil.MD5("123456"));
System.out.println("MD5\t\t" + MessageDigestUtil.MD5("123456"));
System.out.println("MD5\t\t" + MessageDigestUtil.MD5("阿凡达是的撒范德萨发大水分"));
// System.out.println("SHA-1\t" + MessageDigestUtil.SHA1("123456"));
// System.out.println("SHA-224\t" + MessageDigestUtil.SHA224("123456"));
// System.out.println("SHA-256\t" + MessageDigestUtil.SHA256("123456"));
// System.out.println("SHA-384\t" + MessageDigestUtil.SHA384("123456"));
// System.out.println("SHA-512\t" + MessageDigestUtil.SHA512("123456"));
}
// MD5 e10adc3949ba59abbe56e057f20f883e
// SHA-1 7c4a8d09ca3762af61e59520943dc26494f8941b
// SHA-224 f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6
// SHA-256 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
// SHA-384 0a989ebc4a77b56a6e2bb7b19d995d185ce44090c13e2984b7ecc6d446d4b61ea9991b76a4c2f04b1b4d244841449454
// SHA-512 ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
}
package com.kuafu.utils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
public class CipherUtil {
private static List<String> algorithmList = new ArrayList<>(); //算法
private static List<String> modeList = new ArrayList<>(); //模式
private static List<String> paddingList = new ArrayList<>(); //填充模式
static {
algorithmList.add("AES");
algorithmList.add("DES");
algorithmList.add("DESede");//DES3
algorithmList.add("RSA");
modeList.add("CBC");
modeList.add("ECB");
paddingList.add("NoPadding");
paddingList.add("PKCS5Padding");
}
/*
1, 获取Cipher类的对象:Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
参数按"算法/模式/填充模式",
(1)加密算法有:AES,DES,DESede(DES3)和RSA 四种
(2) 模式有CBC(有向量模式)和ECB(无向量模式 适用于大数据量),向量模式可以简单理解为偏移量,使用CBC模式需要定义一个IvParameterSpec对象
(3) 填充模式:
NoPadding: 加密内容不足8位用0补足8位, Cipher类不提供补位功能,需自己实现代码给加密内容添加0, 如{65,65,65,0,0,0,0,0}
PKCS5Padding: 加密内容不足8位用余位数补足8位, 如{65,65,65,5,5,5,5,5}或{97,97,97,97,97,97,2,2}; 刚好8位补8位8
排列组合之后有 这么多的参数:
* AES/CBC/NoPadding (128)
* AES/CBC/PKCS5Padding (128)
* AES/ECB/NoPadding (128)
* AES/ECB/PKCS5Padding (128)
* DES/CBC/NoPadding (56)
* DES/CBC/PKCS5Padding (56)
* DES/ECB/NoPadding (56)
* DES/ECB/PKCS5Padding (56)
* DESede/CBC/NoPadding (168)
* DESede/CBC/PKCS5Padding (168)
* DESede/ECB/NoPadding (168)
* DESede/ECB/PKCS5Padding (168)
* RSA/ECB/PKCS1Padding (1024, 2048) //这个跟java版本有很大关系 具体参考 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/crypto/Cipher.html 这个类的官方文档
* RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
* RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
2,Cipher对象需要初始化 init(int opmode, Key key, AlgorithmParameterSpec params)
(1)opmode :Cipher.ENCRYPT_MODE(加密模式)和 Cipher.DECRYPT_MODE(解密模式)
(2)key :密匙,使用传入的盐构造出一个密匙,可以使用SecretKeySpec、KeyGenerator和KeyPairGenerator创建密匙,其中
* SecretKeySpec和KeyGenerator支持AES,DES,DESede三种加密算法创建密匙
* KeyPairGenerator支持RSA加密算法创建密匙
(3)params :使用CBC模式时必须传入该参数,该项目使用IvParameterSpec创建iv 对象
3,加密或解密
byte[] b = cipher.doFinal(content);
返回结果为byte数组,如果直接使用 new String(b) 封装成字符串,则会出现乱码
4,对加密结果进行一层包装 有两种处理方式:转换为base64的字符串或转换为16进制的字符串
5,如果只是想要加密一个数据的话,推荐使用AES算法 直接:
public static void main(String[] args) throws Exception{
String encrypt = CipherUtil.AesUtil.Ecb.Padding.encrypt("toBeEncryptData", "slatKey1");
System.out.println(encrypt);
String decryptData = CipherUtil.AesUtil.Ecb.Padding.decrypt(encrypt, "slatKey1");
System.out.println(decryptData);
}
* */
public static class AesUtil {
public static class Cbc {
public static class Padding {
/**
* content: 加密内容
* slatKey: 加密的盐,16位字符串
* vectorKey: 加密的向量,16位字符串
*/
public static String encrypt(String content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"), new IvParameterSpec(vectorKey.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,16位字符串
* vectorKey: 加密时使用的向量,16位字符串
*/
public static String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"), new IvParameterSpec(vectorKey.getBytes()));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456";//任意长度
String slatKey = "123456qwerasdfzx"; //长度必须是16位
String vectorKey = "1234qwerasdfzxcv"; //长度必须是16位
final String encrypt = encrypt(content, slatKey, vectorKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey, vectorKey);
System.out.println(decrypt);
}
}
public static class NoPadding {
/**
* content: 加密内容
* slatKey: 加密的盐,16位字符串
* vectorKey: 加密的向量,16位字符串
*/
public static String encrypt(String content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"), new IvParameterSpec(vectorKey.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,16位字符串
* vectorKey: 加密时使用的向量,16位字符串
*/
public static String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"), new IvParameterSpec(vectorKey.getBytes()));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456787890123456";//长度必须是16位
String slatKey = "123456qwerasdfzx"; //长度必须是16位
String vectorKey = "1234qwerasdfzxcv"; //长度必须是16位
final String encrypt = encrypt(content, slatKey, vectorKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey, vectorKey);
System.out.println(decrypt);
}
}
}
public static class Ecb {
public static class Padding {
/**
* content: 加密内容
* slatKey: 加密的盐,16位字符串
* vectorKey: 加密的向量,16位字符串
*/
public static String encrypt16(String content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,16位字符串
* vectorKey: 加密时使用的向量,16位字符串
*/
public static String decrypt16(String base64Content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
/**
* content: 加密内容
* slatKey: 加密的盐,任意位数
*/
public static String encrypt(String content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, getSlatKey(slatKey, "AES"));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,任意位数
*/
public static String decrypt(String base64Content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, getSlatKey(slatKey, "AES"));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456";//任意长度
String slatKey = "123456qw"; //长度必须是16位
final String encrypt = encrypt(content, slatKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey);
System.out.println(decrypt);
}
}
public static class NoPadding {
/**
* content: 加密内容
* slatKey: 加密的盐,16位字符串
*/
public static String encrypt(String content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,16位字符串
*/
public static String decrypt(String base64Content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "AES"));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "1234567890123456";//长度必须是16位
String slatKey = "123456qwerasdfzx"; //长度必须是16位
final String encrypt = encrypt(content, slatKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey);
System.out.println(decrypt);
}
}
}
}
public static class DesUtil {
public static class Cbc {
public static class Padding {
/**
* content: 加密内容
* slatKey: 加密的盐,8位字符串
* vectorKey: 加密的向量,8位字符串
*/
public static String encrypt(String content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "DES"), new IvParameterSpec(vectorKey.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,8位字符串
* vectorKey: 加密时使用的向量,8位字符串
*/
public static String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "DES"), new IvParameterSpec(vectorKey.getBytes()));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456sadfasdfasdf";//任意长度
String slatKey = "12345678"; //长度必须是8位
String vectorKey = "12345678"; //长度必须是8位
final String encrypt = encrypt(content, slatKey, vectorKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey, vectorKey);
System.out.println(decrypt);
}
}
}
}
public static class Des3Util {
public static class Cbc {
public static class Padding {
/**
* content: 加密内容
* slatKey: 加密的盐,24位字符串
* vectorKey: 加密的向量,8位字符串
*/
public static String encrypt16(String content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "DESede"), new IvParameterSpec(vectorKey.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,24位字符串
* vectorKey: 加密时使用的向量,8位字符串
*/
public static String decrypt16(String base64Content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(slatKey.getBytes(), "DESede"), new IvParameterSpec(vectorKey.getBytes()));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,任意字符串
*/
public static String encrypt(String content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, getSlatKey(slatKey, "DESede"), new IvParameterSpec(vectorKey.getBytes()));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的盐,任意字符串
*/
public static String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, getSlatKey(slatKey, "DESede"), new IvParameterSpec(vectorKey.getBytes()));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456sadfasdfasdf";//任意长度
String slatKey = "123456781234567812345678"; //长度必须是24位
String vectorKey = "12345678"; //长度必须是8位
final String encrypt = encrypt(content, slatKey, vectorKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey, vectorKey);
System.out.println(decrypt);
}
}
}
}
public static class RasUtil {
public static class Ecb { //RSA 只支持ECB模式,
public static class Padding {
/**
* 根据slatKey获取公匙,传入的slatKey作为SecureRandom的随机种子,种子相同,生成的密钥相同
* 若使用new SecureRandom()创建公匙,则需要记录下私匙,解密时使用
*/
private static Key getPublicKey(String slatKey) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(slatKey.getBytes());
//同上,传入的盐只作为SecureRandom类的随机种子,盐相同,产生的keyPair的公匙和私匙也是同一对。
//也可以不设置SecureRandom类的随机种子,直接使用new SecureRandom()创建一个新对象,此时就必须记录下公匙和私匙,在解密时使用。
keyPairGenerator.initialize(1024, random);//or 2048
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair.getPublic();
}
/**
* 根据slatKey获取私匙,传入的slatKey作为SecureRandom的随机种子
*/
private static Key getPrivateKey(String slatKey) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(slatKey.getBytes());
keyPairGenerator.initialize(1024, random);// or 2048
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair.getPrivate();
}
/**
* 通过私钥byte[](publicKey.getEncoded())将私钥还原,适用于RSA算法
*/
private static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
InvalidKeySpecException {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法
*/
private static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException,
InvalidKeySpecException {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* content: 加密内容
* slatKey: 加密的种子,
* vectorKey: 加密的向量,
*/
public static String encrypt(String content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.PUBLIC_KEY, getPublicKey(slatKey));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
}
/**
* content: 解密内容(base64编码格式)
* slatKey: 加密时使用的种子
*/
public static String decrypt(String base64Content, String slatKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.PRIVATE_KEY, getPrivateKey(slatKey));
byte[] content = Base64.getDecoder().decode(base64Content);
byte[] encrypted = cipher.doFinal(content);
return new String(encrypted);
}
public static void main(String[] args) throws Exception {
String content = "123456";//任意长度
String slatKey = "afsd"; //任意长度
final String encrypt = encrypt(content, slatKey);
System.out.println(encrypt);
final String decrypt = decrypt(encrypt, slatKey);
System.out.println(decrypt);
}
}
}
}
/*
创建密匙
创建密匙主要使用SecretKeySpec、KeyGenerator和KeyPairGenerator三个类来创建密匙。
1,SecretKeySpec类
SecretKeySpec类支持创建密匙的加密算法(AES,DES,DES3)
SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
注意不同的加密算法的byte数组的长度是不同的,创建密匙前最好先检测下byte数组的长度。各加密算法的密匙长度如下
加密算法 密匙长度 向量长度
AES 16 16
DES 8 8
DES3 24 8
2 KeyGenerator类
KeyGenerator类支持创建密匙的加密算法(ASE,DES,DES3)
3,KeyPairGenerator类
RSA加密算法使用的密匙是包含公匙和私匙两种,一般情况下,有使用公匙加密,则用私匙解密;使用私匙加密,则使用公匙解密。可以使用KeyPairGenerator类来创建RSA加密算法的密匙
KeyPairGenerator类支持创建密匙的加密算法(RSA)
* */
/**
* 获取加密的密匙,传入的slatKey可以是任意长度的,作为SecureRandom的随机种子,
* 而在KeyGenerator初始化时设置密匙的长度128bit(16位byte)
*/
private static Key getSlatKey(String slatKey, String algorithm) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(algorithm);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(slatKey.getBytes());
//KeyGenerator对象在初始化需要传入一个随机源。一般使用的都是SecureRandom类来创建随机源,此时传入的盐只作为SecureRandom类的随机种子,
// 种子相同,产生的随机数也相同;盐的长度不再受限制了,但KeyGenerator对象则必须指定长度。
kgen.init(128, random);
Key key = kgen.generateKey();
return key;
}
}