数据安全管理: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
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Spring源码分析之IOC的三种常见用法及源码实现(二)
回顾上文 我们研究的是 AnnotationConfigApplicationContext annotationConfigApplication = new AnnotationConfigApplicationContext (MainConfig.class); Person person2 = (Person)annotationConfigApplication.getBean("person2"); 这两句话的实现,其中来到了主角儿AnnotationConfigApplicationContext的构造器实现: public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); } 其中this()和register(annotatedClasses);看完了,我们这次来看看refresh(); 一、跟进refresh()的代码 public void refresh() throws ...
- 下一篇
Java描述设计模式(14):解释器模式
本文源码:GitHub·点这里 || GitEE·点这里 一、解释器模式 1、基础概念 解释器模式是对象的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的表达式。 2、模式图解 3、核心角色 (1)、抽象表达式 Express:声明具体表达式角色需要实现的抽象接口,该接口主要提供一个interpret()方法,称做解释操作。 (2)、终结符表达式 TerminalExpress:实现抽象表达式角色接口,主要是一个interpret()方法;每个终结符都有一个具体终结表达式与之相对应。比如解析c=a+b,a和b是终结符,解析a和b的解释器就是终结符表达式。 (3)、非终结符表达式 NotTerminalExpress:每一条规则都需要一个具体的非终结符表达式用来衔接,一般是指运算符或者逻辑判断,比如c=a+b,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。 (4)、环境容器 DataMap:一般是用来存放各个终结符所对应的具体值,比如c=a+b转换为c=1+2。这些信息需要一个存放环境。 4...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS6,7,8上安装Nginx,支持https2.0的开启