数据安全管理:RSA加密算法,签名验签流程详解
本文源码:GitHub·点这里 || GitEE·点这里
一、RSA算法简介
1、加密解密
RSA加密是一种非对称加密,在公开密钥加密和电子商业中RSA被广泛使用。可以在不直接传递密钥的情况下,完成加解密操作。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥。该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。
2、签名验签
数字签名就是信息的来源添加一段无法被伪造的加密字符串,这段数字串作为对信息的来源真实性的一个有效证明。这个过程称为签名和验签。
二、场景描述
- 消息发送方:甲方,持有公钥
- 消息接收方:乙方,持有私钥
1、加密解密过程
(1)、乙方生成一对密钥即公钥和私钥,私钥不公开,乙方自己持有,公钥为公开,甲方持有。
(2)、乙方收到甲方加密的消息,使用私钥对消息进行解密,获取明文。
2、签名验签过程
(1)、乙方收到消息后,需要回复甲方,用私钥对回复消息签名,并将消息明文和消息签名回复甲方。
(2)、甲方收到消息后,使用公钥进行验签,如果验签结果是正确的,则证明消息是乙方回复的。
三、源代码实现
1、密钥字符串获取
- 代码生成
private static HashMap<String, String> getTheKeys() {
HashMap<String, String> keyPairMap = new HashMap<String, String>();
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 密钥大小:1024 位
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
String publicKey = printBase64Binary(keyPair.getPublic().getEncoded());
String privateKey = printBase64Binary(keyPair.getPrivate().getEncoded());
keyPairMap.put("publicKey", publicKey);
keyPairMap.put("privateKey", privateKey);
return keyPairMap ;
}
- 读取文件

文件位置
public static final String PUB_KEY = "rsaKey/public.key" ;
public static final String PRI_KEY = "rsaKey/private.key" ;
文件加载
public static String getKey (String keyPlace) throws Exception {
BufferedReader br= null;
try {
br= new BufferedReader(new InputStreamReader(RsaCryptUtil.class.getClassLoader().
getResourceAsStream(keyPlace)));
String readLine= null;
StringBuilder keyValue = new StringBuilder();
while((readLine= br.readLine())!=null){
if(!(readLine.charAt(0)=='-')){
keyValue.append(readLine);
}
}
return keyValue.toString();
} catch (Exception e) {
throw new Exception("RSA密钥读取错误",e) ;
} finally{
if (br != null) {
try {
br.close();
} catch (Exception e) {
System.out.println("密钥读取流关闭异常");
}
}
}
}
2、公钥和私钥
- 公钥字符串生成公钥
public static RSAPublicKey createPublicKey(String publicKeyValue) throws Exception {
try {
byte[] buffer = DatatypeConverter.parseBase64Binary(publicKeyValue);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
throw new Exception("公钥创建失败", e);
}
}
- 私钥字符串生成私钥
public static RSAPrivateKey createPrivateKey(String privateKeyValue) throws Exception {
try {
byte[] buffer = javax.xml.bind.DatatypeConverter.parseBase64Binary(privateKeyValue);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
throw new Exception("私钥创建失败", e);
}
}
3、加密和解密
- 公钥加密
public static String encrypt(RSAPublicKey publicKey, byte[] clearData) throws Exception {
if (publicKey == null) {
throw new Exception("加密公钥为空, 无法加密");
}
try {
Cipher cipher = Cipher.getInstance("RSA") ;
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] output = cipher.doFinal(clearData);
return printBase64Binary(output);
} catch (Exception e) {
throw new Exception("公钥加密失败",e);
}
}
- 私钥解密
public static String decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
if (privateKey == null) {
throw new Exception("解密私钥为空, 无法解密");
}
try {
Cipher cipher = Cipher.getInstance("RSA") ;
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] output = cipher.doFinal(cipherData);
return new String(output);
} catch (BadPaddingException e) {
throw new Exception("私钥解密失败",e);
}
}
4、签名和验签
- 私钥签名
public static String sign (String signData, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(signData.getBytes());
return printBase64Binary(signature.sign());
}
- 公钥验签
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(parseBase64Binary(sign));
}
5、编码和解码
/**
* 字节数组转字符
*/
public static String printBase64Binary(byte[] bytes) {
return DatatypeConverter.printBase64Binary(bytes);
}
/**
* 字符转字节数组
*/
public static byte[] parseBase64Binary(String value) {
return DatatypeConverter.parseBase64Binary(value);
}
6、测试代码块
- 密钥生成测试
public static void testCreateKey () throws Exception {
HashMap<String, String> map = RsaCryptUtil.getTheKeys();
String privateKeyStr=map.get("privateKey");
String publicKeyStr=map.get("publicKey");
System.out.println("私钥:"+privateKeyStr);
System.out.println("公钥:"+publicKeyStr);
//消息发送方
String originData="cicada-smile";
System.out.println("原文:"+originData);
String encryptData = RsaCryptUtil.encrypt(RsaCryptUtil.createPublicKey(publicKeyStr),
originData.getBytes());
System.out.println("加密:"+encryptData);
//消息接收方
String decryptData=RsaCryptUtil.decrypt(RsaCryptUtil.createPrivateKey(privateKeyStr),
RsaCryptUtil.parseBase64Binary(encryptData));
System.out.println("解密:"+decryptData);
}
- 密钥读取测试
public static void testReadKey () throws Exception {
String value = getKey("rsaKey/public.key");
System.out.println(value);
String privateKeyStr = getKey(RsaCryptUtil.PRI_KEY) ;
String publicKeyStr = getKey(RsaCryptUtil.PUB_KEY) ;
//消息发送方
String originData="cicada-smile";
System.out.println("原文:"+originData);
String encryptData = RsaCryptUtil.encrypt(RsaCryptUtil.createPublicKey(publicKeyStr),
originData.getBytes());
System.out.println("加密:"+encryptData);
//消息接收方
String decryptData=RsaCryptUtil.decrypt(RsaCryptUtil.createPrivateKey(privateKeyStr),
RsaCryptUtil.parseBase64Binary(encryptData));
System.out.println("解密:"+decryptData);
}
- 签名验签测试
public static void testSignVerify () throws Exception {
String signData = "cicada-smile" ;
String privateKeyStr = getKey(RsaCryptUtil.PRI_KEY) ;
String publicKeyStr = getKey(RsaCryptUtil.PUB_KEY) ;
String signValue = sign(signData,RsaCryptUtil.createPrivateKey(privateKeyStr)) ;
boolean flag = verify(signData,RsaCryptUtil.createPublicKey(publicKeyStr),signValue);
System.out.println("原文:"+signData);
System.out.println("签名:"+signValue);
System.out.println("验签:"+flag);
}
四、源代码地址
GitHub·地址
https://github.com/cicadasmile
GitEE·地址
https://gitee.com/cicadasmile

数据安全管理:RSA加密算法,签名验签流程详解的更多相关文章
- 利用SHA-1算法和RSA秘钥进行签名验签(带注释)
背景介绍 1.SHA 安全散列算法SHA (Secure Hash Algorithm)是美国国家标准和技术局发布的国家标准FIPS PUB 180-1,一般称为SHA-1.其对长度不超过264二进制 ...
- RSA密钥生成、加密解密、签名验签
RSA 非对称加密公钥加密,私钥解密 私钥签名,公钥验签 下面是生成随机密钥对: //随机生成密钥对 KeyPairGenerator keyPairGen = null; try { keyPair ...
- js rsa sign使用笔记(加密,解密,签名,验签)
你将会收获: js如何加密, 解密 js如何签名, 验签 js和Java交互如何相互解密, 验签(重点) 通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方 ...
- [Python3] RSA的加解密和签名/验签实现 -- 使用pycrytodome
Crypto 包介绍: pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以 ...
- RSA签名验签
import android.util.Base64; import java.security.KeyFactory; import java.security.PrivateKey; import ...
- C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServic
C#在using System.Security.Cryptography下有 DESCryptoServiceProvider RSACryptoServiceProvider DESCryptoS ...
- RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密
原文:RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密 C#在using System.Security.Cryptograph ...
- php 实现签名验签
本人php菜鸟,主要使用php实现简单的签名验签功能 以下php代码使用的密钥格式为pem格式,其他证书格式可以使用openssl进行转换(未安装请实现安装): 以下是.p12文件导出pem格式公私钥 ...
- .net 实现签名验签
本人被要求实现.net的签名验签,还是个.net菜鸡,来分享下采坑过程 依然,签名验签使用的证书格式依然是pem,有关使用openssl将.p12和der转pem的命令请转到php实现签名验签 .ne ...
随机推荐
- exportfs命令、NFS客户端问题、FTP介绍、使用vsftpd搭建ftp
6月22日任务 14.4 exportfs命令14.5 NFS客户端问题15.1 FTP介绍15.2/15.3 使用vsftpd搭建ftp 14.4 exportfs命令 当我们修改nfs的配置文件e ...
- python_网络编程
网络ISO(国际标准化组织)--->网络体系结构标准(OSI模型)OSI: 网络信息传输比较复杂需要很多功能协同-->将功能分开,降低耦合度,让每个模块完成一定的功能-->将这些模块 ...
- NSURLConnection发送GET请求
// ViewController.m // 04-掌握-NSURLConnection发送GET请求 // // Created by xiaomage on 16/2/22. // Copyrig ...
- tp5引用第三方类vendor或extend(多种方法)
extend 方法一:命名空间引入 我们只需要把自己的类库包目录放入EXTEND_PATH目录(默认为extend,可配置),就可以自动注册对应的命名空间,例如: 我们在extend目录下面新增一个l ...
- ajax加载引起瀑布流布局堆叠
jQuery 瀑布流使用ajax加载数据库图片url ,ajax每次请求到的数据不变时,瀑布流效果没问题. 但当请求到的数据变化时,瀑布流图片格式会重叠 或者相隔很远等等的格式问题,这是由于图片加载是 ...
- Scrapy+eChart自动爬取生成网络安全词云
因为工作的原因,近期笔者开始持续关注一些安全咨询网站,一来是多了解业界安全咨询提升自身安全知识,二来也是需要从各类安全网站上收集漏洞情报. 作为安全情报领域的新手,面对大量的安全咨询,多少还是会感觉无 ...
- ModelArts微认证零售客户分群知识点总结
\ 作者:华为云MVP郑永祥
- 关于TC297的Flash写入之前是否需要先擦除的问题
通过实际测试,对TC297 Flash的一个地址空间可以重复执行写入操作(program),而不需要先对该区域所在扇区进行擦除. MPC5675K则需要在写入之前进行擦除.
- IO到NIO的一个转变
本内容来源:Jack视频讲解和自己的一个理解. 1.故事还得从网络模型或者IO开始聊起 2.你有想过传统IO真正存在的问题吗? 3.如果你是设计者,IO可以怎样改进? 4.NIO原理分析以及代码实现 ...
- Sql Server连表查询字段为null
这是一个坑,并且是有毒的坑. 一不小心我就掉进了这个坑里面,费了好大的力气这才从坑里面爬出来. 话不多说,开始吹BB啦. 一.简单说说遇到的问题: 连表查询,一对多. 出现 int, smallda ...