消息摘要算法
本文档依赖的jar maven地址如下:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.57</version>
</dependency>
分类名词解释
- MD
message Digest 消息摘要 - SHA
Secure hash algorithm安全散列 - MAC
message authenttication code 消息认证码
三个名词的作用
验证数据的完整性(比如maven仓库的md5数据完整性比对)
消息摘要算法是数字签名的核心算法
MD算法分类
- MD5
- MD家族(生成都是128位摘要信息 如果md2,md4)
MD算法特点
单项加密
不可逆
MD5的实现方
package com.ztgeo.secret;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
public class MDDemo {
//md家族的加解密算法
private static String reqStr= "MD5需要加密的数据";
public static void main(String[] args) {
secretMD5();
}
public static void secretMD5(){
try {
//使用原生jdk就可以进行md5的加密
MessageDigest md = MessageDigest.getInstance("MD5");
//进行消息摘要(md5加密)
byte[] md5Bytes =md.digest(reqStr.getBytes());
System.out.println("md5加密后未经转换的byte[]后的结果:"+md5Bytes);
System.out.println("md5加密后转换成string后的结果:"+new String(md5Bytes));
//转换后的长度没有128 只有11位 就算转换成string也是如下乱码:������'�?9�O��s4
//所以md5加密后的数据 不能直接使用 应该使用16进制转换后的结果作为加密结果
//恰巧bc和cc中都有该功能的方法 一般选择cc中方法
System.out.println("转换成16进制之后的加密数组:"+Hex.encodeHexString(md5Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
该算法 也同样支持md2 只需要在获得实例的时候传入"MD2"即可
但是jdk没有提供md4的实现 强制使用md4获得实例会报错
使用bc实现md4或者其他加密方式
private static void BCMD4(){
//使用bc包实现md4的算法 加密
Digest digest = new MD4Digest();
//预处理 md4需要加密的字符串(类似读取 输入流)
digest.update(reqStr.getBytes(), 0,reqStr.getBytes().length);
//使用byte数组去接收结果 相当于处理完了 用容器去承载结果
byte[] md4Byte = new byte[digest.getDigestSize()];
///读出到输入流
digest.doFinal(md4Byte, 0);
//这个时候结果容器被装满 使用bc自带的64位转码进行转码
System.out.println("BC加密后的MD4加密结果:"+org.bouncycastle.util.encoders.Hex.toHexString(md4Byte));
}
当然 也可以用cc去实现相同的功能 只是在cc中并没有提供md4的实现,猜测cc只是简化辅助jdk的md功能 没有做功能的延伸
//使用cc实现md的加密
//如果看源码会发现 实际上cc并没有去自己写md的实现 只是引用来了jdk的md相应实现
public static void ccMD5(){
//这里需要提的而是 cc实现 md5的方法中 有个方法简化了hex转化64位的操作
System.out.println("CCmd5的简单实现:"+DigestUtils.md5Hex(reqStr.getBytes()));
}
md算法的总结
- 使用jdk的方法是偏底层的,不提供16进制转换
- bc的优势在于提供了md4的实现(jdk和cc没有)
- cc实现了hex进制转换的直接使用 但只是简化了jdk的方法 没有自己实现
md加密方式的应用
注册时用户名明文 密码变为不可逆 密文 存入数据库
登录时用户名明文 密码直接拿去数据库比对
这样有效的防止了信息泄露(就算拿到数据库还是不知道密码)
SHA
- 安全散列算法
- 固定长度的摘要信息
- 很多场景下 被称为md5的继承者
- 美国国家安全局设计的(背景强大)
- 由MD4演变而来
- 内容稍有不同结果就大相径庭 很难被破译
SHA的分类
- SHA-1
- SHA-2
- SHA-224
- SHA-256
- SHA-384
- SHA-512
算法的实现
依然没有cc的算法.是因为cc又是对jdk的简化操作
SHA的算法应用
防止数据传输过程中被篡改,保证数据的完整性
常用的传输方式是在url上传参 并发送sha的消息摘要,,对方进行消息摘要的对比 看传输数据是否发生了篡改
MAC
- 兼容了md和sha的特性
- 加入了秘钥(hmac 含有秘钥的sha算法)
MAC的分类
-
MD系列
- HmacMD2
- HmacMD4
- HmacMD5
-
SHA系列
- HmacSHA1
- HmacSHA2
- HmacSHA224
- HmacSHA256
- HmacSHA384
- HmacSHA512
MAC算法的摘要长度和实现方
MAC的代码实现
package com.ztgeo.secret;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
public class MacDemo {
//mac安全散列算法的实现(有秘钥)
private static String reqStr="需要被mac摘要的数据";
public static void main(String[] args) {
jdkHmacMD5();
bHmacMD5();
}
public static void jdkHmacMD5(){
try {
//获得秘钥工厂
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
//一下两步是是随机生产key 但实际情况 需要制定key
/*//生成秘钥
SecretKey key = keyGenerator.generateKey();
//获得秘钥
byte[] keyByte = key.getEncoded();*/
byte[] keyByte = org.apache.commons.codec.binary.Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'});
//还原秘钥 数组秘钥 通过类进行还原
SecretKey restoreKey = new SecretKeySpec(keyByte, "HmacMD5");
//实例化MAC 使用秘钥还原
Mac mac = Mac.getInstance(restoreKey.getAlgorithm());
//初始化mac
mac.init(restoreKey);
//执行加密(摘要)
byte[] HmacMd5Bytes = mac.doFinal(reqStr.getBytes());
//输出摘要的结果
System.out.println("jkd hmacMD5结果:"+Hex.toHexString(HmacMd5Bytes));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DecoderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//bc实现mac md5算法
public static void bHmacMD5(){
//实例化mac
HMac hmac = new HMac(new MD5Digest());
//初始化mac
hmac.init(new KeyParameter(Hex.decode("aaaaaaaaaa")));
//读入流
hmac.update(reqStr.getBytes(),0,reqStr.getBytes().length);
//准备容器
byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
//放置输出结果
hmac.doFinal(hmacMD5Bytes, 0);
//输出结果
System.out.println("bcHmacMD5结果:"+Hex.toHexString(hmacMD5Bytes));
}
}
对称加密算法
加密秘钥和解密秘钥相同
对称加密算法的特点
- 初等的加密算法(安全级别不高)
- DES(代表性的加密算法,长度不够 安全性低 已被破解)
- 3DES
- AES(替代DES)
- PBE
- IDEA
DES详解
出身
ibm提交美国,98年后被破解,目前不具备安全性
实现方式和实现方
使用jdk实现DES算法的加解密
package com.ztgeo.secret;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Hex;
public class DESDemo {
private static String reqStr ="需要被加密内容!!";
public static void main(String[] args) {
jdkDES();
}
public static void jdkDES(){
try {
//生成秘钥材料
/*KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
//指定秘钥长度 DES是56位
keyGenerator.init(56);
SecretKey key = keyGenerator.generateKey();
//获得程序产生的key
byte[] keyByte = key.getEncoded();*/
//当然 可以自己指byte数组类型的秘钥
byte[] keyByte = "15062101243".getBytes(); //秘钥
//秘钥材料转换
DESKeySpec desKeySpec = new DESKeySpec(keyByte);
//生成真正的key
//实例化秘钥工厂(指定加密方式)
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 (需要填充加解密的算法/工作方式/填充方式)
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
//加密模式ENCRYPT_MODE 和转换可以使用的key
cipher.init(cipher.ENCRYPT_MODE, convertSecretKey);
//执行加密操作
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用JDK加密DES:"+Hex.encodeHexString(result));
//解密操作
//依然使用cipher进行解密 需要的秘钥 也需要秘钥转换
cipher.init(cipher.DECRYPT_MODE, convertSecretKey);
//执行加密操作 结果转成string
result = cipher.doFinal(result);
System.out.println("使用JDK解密DES:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//bc的DES实现 可以通过secret添加provide进行实现 实现方式和jdk类似 这里不做赘述
}
3DES(三重DES)
三重DES的必要性
- DES违反了柯克霍夫原则(算法半公开) 所以安全性不高
- DES的背景是美国安全局,所以是否有后门 不敢确保
三重DES的好处
- 密码长度增强
- 迭代次数增多
长度和实现方
JDK的实现
package com.ztgeo.secret;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Hex;
public class DES3 {
private static String reqStr ="需要被加密内容!!";
public static void main(String[] args) {
jdk3des();
}
public static void jdk3des(){
//jdk的三重des和des实现都是类似的 我们直接copy代码
try {
//生成秘钥材料
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
//指定秘钥长度 3DES是168位
//keyGenerator.init(168);
//当然 如果不想记什么算法多少位 可以使用根据getInstance对字符串变能量获得默认长度的秘钥
keyGenerator.init(new SecureRandom());
SecretKey key = keyGenerator.generateKey();
//获得程序产生的key
byte[] keyByte = key.getEncoded();
//当然 可以自己指byte数组类型的秘钥 但目前报错 原因未知
//byte[] keyByte = "15062101243".getBytes(); //秘钥
//秘钥材料转换
DESedeKeySpec desKeySpec = new DESedeKeySpec(keyByte);
//生成真正的key
//实例化秘钥工厂(指定加密方式)
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 (需要填充加解密的算法/工作方式/填充方式)
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
//加密模式ENCRYPT_MODE 和转换可以使用的key
cipher.init(cipher.ENCRYPT_MODE, convertSecretKey);
//执行加密操作
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用JDK加密3DES:"+Hex.encodeHexString(result));
//解密操作
//依然使用cipher进行解密 需要的秘钥 也需要秘钥转换
cipher.init(cipher.DECRYPT_MODE, convertSecretKey);
//执行加密操作 结果转成string
result = cipher.doFinal(result);
System.out.println("使用JDK解密3DES:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
AES
AES的产生原因
- DES安全性不要
- 3DES效率不高
- AES是DES(包括3DES的替代品)
- 对称加密的首选就是AES 使用率最高
- AES目前官方并没有确认被破解
AES的应用范围
AES用于移动通讯系统加密以及基于SSH协议的软件
算法实现
jdk的实现(bc的实现和aes十分类似 不举例了)
package com.ztgeo.secret;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class AESDemo {
private static String reqStr ="需要被加密内容!!";
public static void main(String[] args) {
jdkAes();
}
public static void jdkAes(){
try {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey sekey = keyGenerator.generateKey();
//获得程序产生的key
byte[] keyByte = sekey.getEncoded();
//转换key
Key key = new SecretKeySpec(keyByte, "AES");
//加密 填充
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] resultByte = cipher.doFinal(reqStr.getBytes());
System.out.println("AES加密后的内容(base64之后):"+Base64.encodeBase64String(resultByte));
//解密
cipher.init(Cipher.DECRYPT_MODE, key);
resultByte = cipher.doFinal(resultByte);
System.out.println("使用JDK解密AES操作:"+new String(resultByte));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
对称加密算法之----PBE
- pbe算法结合了消息摘要算法和对称加密算法的所有优点
- pbe(password based encryption)基于口令的加密
- 只是对已有算法的包装
- JDK,BC
- 盐(秘钥口令和扰码)
- 是一种综合性算法(消息摘要+对称加密) 常见 PBEWithMD5AndDES
PBE算法的实现
演示jdk实现PBE的算法
package com.ztgeo.secret;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.apache.commons.codec.binary.Base64;
public class PBEDemo {
private static String reqStr = "需要被加密的内容";
public static void main(String[] args) {
jdkPBE();
}
public static void jdkPBE(){
try {
//初始化盐 盐可以理解为随机数
SecureRandom random = new SecureRandom();
//用8位 产生盐
byte[] salt = random.generateSeed(8);
//口令转秘钥
String password = "12345687";
//密码转换成口令秘钥
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
Key key = factory.generateSecret(pbeKeySpec);
//加密
//将盐构成params
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, key,parameterSpec);
byte[] byteResult = cipher.doFinal(reqStr.getBytes());
System.out.println("jdk使用PBE加密后的结果:"+ Base64.encodeBase64String(byteResult));
//解密
cipher.init(Cipher.DECRYPT_MODE,key,parameterSpec);//秘钥 盐
byteResult = cipher.doFinal(byteResult);
System.out.println("jdk使用PBE解密后的结果:"+ new String(byteResult));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PBE在的实际使用
由图中可以看出,解谜.不仅要知道解密的秘钥,还要知道加密时实时产生的随机数才能正确解密,极大提高了数据性;
非对称加密算法
因为对称加密算法是双方秘钥相同.所以又叫做初等加密算法
非对称加密算法的特点
- 高级加密算法(秘钥不对称)
- 双保险(类似vip银行客户保险柜原理.银行一把钥匙.客户一把钥匙)
- 公钥,私钥 (都是成对出现的)
非对称加密的分类
- DH(Diffie-Hellman)密钥交换算法
- RSA-基于因子分解(三个人姓氏开头,应用最广)
- ElGamal-基于离散对数
- ECC(椭圆曲线加密)
DH加密算法
- 非对称加密的鼻祖
- 是为了解决对称加密算法密钥的传输安全级别低的问题应运而生的
- 构建本地秘钥 解决秘钥传递的问题
DH相关实现方
JDK实现加密算法使用类
加密方:
- KeyPairGenerator 秘钥对的 生产类
- KeyPair 秘钥对 可以产生公钥和私钥
- PublicKey 公钥
解密方:
- KeyFactory 秘钥工厂(根据规范生成公钥私钥) 还原秘钥
- X509EncodeKeySpec 根据ASN.1进行秘钥编码
- DHPublicKey
- DHParameterSpec DH算法中 参数的集合类
- KeyPairGenerator
- PrivateKey
秘钥构建
KeyAgreement 提供秘钥协议的类
SecretKey 秘密秘钥 生成分组的秘密秘钥
加密,解密
Cipher 加密解密 提供密码功能类
DH加密的步骤
- 发送方发送公钥载体
- 接收方根据发送方公钥产生接收方公钥载体
- 根据接受方公钥载体产生本地秘钥
- 发送接收方公钥载体
- 接收方根据接收方的公钥载体 产生本地秘钥
- 对比双方本地秘钥 完全相同后发送方根据本地秘钥加密数据
- 接收方 根据本地秘钥进行 解密数据
在此过程中,双方的本地秘钥不同,但两次发送,彼此依赖生成,形成完美的闭环,具体代码如下:
package com.ztgeo.secret;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
//非对称加密
public class DHDemo {
private static String reqStr = "需要被加密的数据123456";
public static void main(String[] args) {
try {
//1.初始化发送方的秘钥
//钥匙对工厂产生钥匙对
KeyPairGenerator sendKeyPairGenerator = KeyPairGenerator.getInstance("DH");
sendKeyPairGenerator.initialize(512);
//钥匙对 用来存放公钥和私钥
KeyPair sendKeyPair =sendKeyPairGenerator.generateKeyPair();
//获得公钥载体 发送给接收方 (网络,文件...)
byte[] sendPublicKeyEnc = sendKeyPair.getPublic().getEncoded();
//2.初始化接收方秘钥 推算出 公钥
KeyFactory reciverKeyFactory = KeyFactory.getInstance("DH");
//秘钥标准
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(sendPublicKeyEnc);
//通过标准和 公钥载体 获得公钥
PublicKey reciverPublicKey = reciverKeyFactory.generatePublic(x509EncodedKeySpec);
//获得公钥参数 用来构建钥匙对
DHParameterSpec dhParameterSpec = ((DHPublicKey)reciverPublicKey).getParams();
//从发送方载体中获得了公钥参数 可以构建 参数对了
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
//接收方 公钥载体
byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
//3.秘钥构建(私钥) 具体可分为 发送方的私钥构建 和接收方的 私钥构建
//接受方
KeyAgreement receviverKeyAgreement = KeyAgreement.getInstance("DH");
//使用私钥进行初始化
receviverKeyAgreement.init(receiverKeyPair.getPrivate());
receviverKeyAgreement.doPhase(reciverPublicKey, true);
//本地私钥产生 并发送
SecretKey receiverDesKey = receviverKeyAgreement.generateSecret("DES");
//发送方(根据接收方 第一次返回的公钥载体进行生成私钥 并反推成本地秘钥)
KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(sendKeyPair.getPrivate());
senderKeyAgreement.doPhase(senderPublicKey, true);
SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
//接收方 根据发送方私钥产生了 本地秘钥
//发送方 也根据接收方传过来的 公钥 产生了本地秘钥
//验证 双方本地秘钥是否相同
if(Objects.equals(receiverDesKey, senderDesKey)){
System.out.println("验证成功,双方产生的本地秘钥相同!!");
}
//4.加密数据
//发送方根据 本地 私钥 加密数据
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用DH加密的数据是:"+Base64.encodeBase64String(result));
//5.客户端解密数据
//接收方根据 本地秘钥进行解密
cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
result = cipher.doFinal(result);
System.out.println("使用DH解密后的数据是:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
具体实现的流程图如下:
流程模板分析
1、甲方(消息发送方,下同)构建密钥对(公钥+私钥),甲方公布公钥给乙方(消息接收方,下同)
2、乙方以甲方发送过来的公钥作为参数构造密钥对(公钥+私钥),将构造出来的公钥公布给甲方
3、甲方用“甲方的私钥+乙方的公钥”构造本地密钥
4、乙方用“乙方的私钥+甲方的公钥”构造本地的密钥
5、这个时候,甲乙两方本地新构造出来的密钥应该一样。然后就可以使用AES这类对称加密算法结合密钥进行数据的安全传送了。传送过程参考AES的相关算法
DH加密算法较为复杂,进一步学习可以参考这篇博客
http://blog.csdn.net/kongqz/article/details/6302913
非对称加密算法-RSA
- 唯一广泛接受并实现
- 可用于数据加密&数字签名
- 公钥加密,私钥解密
- 私钥加密,公钥解密
RSA长度和填充及是实现方式
具体实现:
package com.ztgeo.secret;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
import com.sun.org.apache.xml.internal.security.encryption.CipherData;
public class RSADemo {
private static String reqStr = "需要被加解密的字符串!!12345689";
public static void main(String[] args) {
jdkRSA();
}
public static void jdkRSA(){
try {
//1.初始化秘钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
//公钥 私钥
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey rasPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
System.out.println("公钥:"+Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("私钥:"+Base64.encodeBase64String(rasPrivateKey.getEncoded()));
//2.使用私钥加密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rasPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);//私钥加密
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("RSA私钥加密后的结果:"+Base64.encodeBase64String(result));
//3.发送发 发送公钥 接收方使用公钥解密 密文
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("公钥解密的结果是:"+new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}
网友评论