非对称加密下RSA在Java的简明教程
引言
在现实世界中,每个人都有自己的密码。在各种系统中都有各类加密和解密的需求。 本文将详细介绍一下RSA的前身后世,应用场景和在Java中的实现,从理论到实践,一步到位,触手可用。
非对称加密与对称加密
对称加密(Symmetric Cryptography)
对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种方法在密码学中叫做对称加密算法。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。
关于对称加密的概念非常容易理解,在现实实际中应用广泛,具体的加密算法都是依赖于秘钥的长度和加解密所需的资源和时间,这里需要一个平衡的。
比如DES, 3DES, AES等等都属于对称加密算法。
非对称加密(Asymmetric Cryptography)
1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。
非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥、公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄。而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人–银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
公私钥体系很好地解决了陌生人通信中加密和解密的问题, 但是加密和解密速度比较慢,如果数据量比较大,则用其加解密不太现实,时间和资源所需都比较大。
非对称加密体系下的数据传输过程,可以参照下图:
在上图中,加密和解密分别使用不同的秘钥,从而很好地解决了秘钥传输的问题,不同的人可以使用不同的秘钥来加解密数据。 这里还有一个非常重要的概念是CA中心,Certificate Authority证书中心的概念。 由于公钥是可以被所有人任意获取的,公开使用的,证书之间也可以基于签名来建立一个信任的链条。从而针对证书建立起来一整套追踪和管理的体系。这里不再赘述这个内容,感兴趣的读者可以参照CA的证书体系获取更多信息。
在这幅图中,体现了CA的价值。CA主要是在商业系统中用以分发和管理证书的一套系统,默认情况下,也可以直接线下发送证书。这里仅仅是为大家普及一个CA概念。
RSA
在非对称加密算法中,存在着RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等诸多算法,相比而言RSA是其中应用最为广泛的一种加密算法。
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年7月首次在美国公布,当时他们三人都在麻省理工学院工作实习。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战和质疑。
RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
对于普通的开发者而言,对于这些信息仅需要了解即可,对于大家来说,了解其原理是为了更好地使用这些算法来服务于我们的系统。
RSA的应用场景(通信,签名和完整性)
通信加解密
由于非对称加密方法中存在加解密速度慢的问题,对于大的数据由于时间和资源的约束无法商业使用,则采取了这种的方法进行加密:
. 使用对称秘钥进行内容加密,比如DES之类的算法,速度快
. 使用非对称算法针对秘钥进行加密, 确保秘钥的安全
. 一事一秘, 每次通信可以采取动态的秘钥,每次都动态生成秘钥
目前来说,主流的通信机制都是采用这种方式,这个是原理上的方式,但不是实际商业上的方式,实际上的商业方式,相比这种方式会更复杂,具体的一种方式如下:
- 通信双方A和B,各自持有一对公私钥对,且且持有对方的公钥
- 基于公钥信息,加密通信认证信息,建立可信任连接
- 在建立可信任连接之后,动态创建一套公私钥对C,在A和B之间共享
- 使用动态生产呢个的公私钥对,来进行实际的通信。
相比于原理上的非对称加密通信而言,实际中的通信机制往往会更复杂,考虑到强度和安全性的问题。
签名认证
除了加解密之外,还有在实际中广泛使用的签名认证。 签名证书的用途:加入有A用户向B用户发送了信息“A love you”,B接收到之后怎么确定就是A发送的呢(因为中间人攻击中,假如C截获了A发送的信息后,改成“C love you”,B是无法确定这两个信息的发送者,因他她们都同样用B的工要加密),于是产生了签名证书技术。
签名证书是由CA用自己的私钥对用户的信息进行加密,并把发给用户的,用户可以在发送信息的过程中附加上自己的签名证书,让接受者验证信息的来源。当接受者接受到发送者的签名证书后即可用ca的公钥解密验证发送者的身份信息。
RSA在Java的实现示例
主要的Java实现如下:
public class RSAUtil {public static final String RSA_ALGORITHM = "RSA";public static final String SIGNATURE_ALGORITHM = "MD5withRSA";public static final Charset UTF8 = Charset.forName("UTF-8");/*** 入口的publicKey是基于Base64编码过的,需要解码* data为实际的数据, sign:摘要信息*/public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes = base64Decode(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);// 取公钥匙对象PublicKey pubKey = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(base64Decode(sign));}/*** 基于字符数组,获取公钥信息。*/public static PublicKey getPublicKey(byte[] publicKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {KeyFactory keyFactory = KeyFactory.getInstance("RSA");X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(publicKeyBytes);RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);return publicKey;}/*** 基于字符数组获取privateKey私钥信息*/public static PrivateKey getPrivatekey(byte[] privateKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {KeyFactory keyFactory = KeyFactory.getInstance("RSA");PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKeyBytes);RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);return privateKey;}/*** 这里并未强制要求数据使用Base64进行编码或者解码操作,开发者自行决定。*/public static byte[] encrypt(PrivateKey privateKey, byte[] bytes) throws Exception {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(bytes);}/*** 这里并未强制要求数据使用Base64进行编码或者解码操作,开发者自行决定。*/public static byte[] decrypt(PublicKey publicKey, byte[] encrypted) throws Exception {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(encrypted);}private static KeyPair buildKeyPair() throws NoSuchAlgorithmException {final int keySize = 2048;KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);keyPairGenerator.initialize(keySize);return keyPairGenerator.genKeyPair();}/*** base64的编码*/public static String base64Encode(byte[] data) {return new BASE64Encoder().encode(data);}/*** base64的解码*/public static byte[] base64Decode(String data) throws IOException {return new BASE64Decoder().decodeBuffer(data);}
}
在上述的代码示例中,提供了加密和解密方法,但是都并未要求使用base64解码和编码实现,开发者可以自行决定是否使用,在外层方法嵌套或者将base64方法放入decrpt/encrpt方法之内实现。
在此实现中提供了verify方法用以验证sign是否正确,签名认证方法。
这里使用了JDK中rt.jar中内置的sun.misc中的Base64的编码和解码方法,如果不喜欢依赖于Oracle的JDK,可以选用Apache的codec包,在maven中配置如下依赖接口:
<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.11</version>
</dependency>
具体的使用方法,可以参考网上的相关资料。
总结
加解密的算法虽然其中涵盖了复杂的数据算法,但是使用起来还是非常简单方便的,只要了解其中的主要原理和应用场景,把握重要的算法关键点,即可满足我们的基本需求。
关于我自己
这些技巧和总结都是来自于实际的工作,欢迎大家反馈和提出自己的意见。
文章也会同步发在今日头条的头条号上,搜索 “程序加油站”,就可以找到。
非对称加密下RSA在Java的简明教程相关推荐
- 非对称加密之RSA算法
非对称加密之RSA算法 1. RSA算法简述 2. 模型分析 3.代码实现 3.1 算法实现 3.2 测试代码 3.3 测试结果 4. 算法实现分析 5. 数据分段处理 该系列文章列表 1.网络及数据 ...
- java程序设计简明教程张晓龙_Java网络编程简明教程
Java网络编程简明教程 网络编程 计算机网络相关概念 计算机网络是两台或更多的计算机组成的网络,同一网络内的任意两台计算机可以直接通信,所有计算机必须遵循同一种网络协议. 互联网 互联网是连接计算机 ...
- 一周极客热文:Java 8简明教程
该教程将带领你一步一步地认识这门语言Java 8的新特性.通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复注解.看完这篇教程后,你还将对最新推出的API有一 ...
- java 大学简明教程_Simply-Java 《JAVA大学简明教程:实例程序设计》例子及习题源代码 - 下载 - 搜珍网...
JAVA大学简明教程:实例程序设计/附书源代码/Tutorial01/MovingShapes/BoundedShape.class JAVA大学简明教程:实例程序设计/附书源代码/Tutorial0 ...
- Java Web 简明教程
点此查看 所有教程.项目.源码导航 1. 前言 本教程用于介绍Java Web开发入门的方方面面,包括开发环境.工具.网页.Java.数据库等. 本教程写于2016年底,一些内容相对比较陈旧了,新版的 ...
- 对称加密、非对称加密、RSA、消息摘要、数字签名、数字证书与 HTTPS 简介
文章目录 1.加密算法简介 1.1 对称加密(Symmetric Key Algorithms) 1.2 非对称加密(Asymmetric Key Algorithms) 1.3 非对称加密 RSA ...
- 图文结合彻底理解非对称加密、RSA原理及安全性(图文版)
博主:爱码叔 个人博客站点: icodebook 公众号:漫话软件设计 专注于软件设计与架构.技术管理.擅长用通俗易懂的语言讲解技术.对技术管理工作有自己的一定见解.文章会第一时间首发在个站上,欢迎大 ...
- java程序设计简明教程答案张晓龙_java2简明教程部分课后复习题答案
JAVA2 简明教程习题答案 第二章 课堂习题 : public class Main { public static void main(String[] args) { //initializat ...
- android java rsa加密_Android RSA与Java RSA加密不一样标准产生问题的解决方法
最近作一个基于android的客户端,客户端与Java服务器 (MyEclipse自带的Tomcat服务器)的通讯须要实施安全方案.而本人是使用非对称密钥来对数据进行加密的,客户端用公钥加密,服务器用 ...
最新文章
- python正则表达regex_Python 正则表达式(RegEx)
- html sql注入_Web安全-SQL注入(sqli-lab)
- 如何在 Asp.Net Core 中 管理敏感数据
- 数据结构与算法--求1~n能组成的所有二叉搜索树的排列
- java开发一款坦克大战游戏
- 内网渗透,横向移动总结(mimikatz域控)
- php编译时出错make: *** [libphp5.la] Error 1
- 用java编写战舰 游戏吗_如何在Java中正确建模战舰游戏
- hiberante中get和load方法的区别
- 机器学习 - 贝叶斯网络
- 画图别存为png 透明_怎么样是使(PNG格式)图片背景透明
- 微信公众号起名字攻略:怎么给公众号取名字?
- python for循环求1到100的和_python如何计算1到100的和(用for循环)
- VC++6.0 用gSoap客户端访问WebService
- 两道小学生的题----1000: 梦里的难题、1002: 拳皇
- Linux 下 启动 Oracle
- DHCP 实现动态 IP 上网简析
- 外链屏蔽解除?QQ还是打不开淘宝、抖音链接
- 《当程序员的那些狗日日子》(五十六)步入正轨
- mac安装powerdesigner
热门文章
- android loadsvm raw,OpenCV机器学习:Android上利用SVM实现手写体数字识别
- uni-app实现微信小程序长按拍视频的功能
- 铁乐学Python_day05-字典dict
- OpenGL3D图形、旋转、纹理、键盘移动、光照、滤波、透明(完整)
- C++实现的基于α-β剪枝算法的井字棋游戏
- 机器学习系列(一), 监督学习和无监督学习
- 网络安全与计算机信息管理论文,计算机信息管理技术在网络安全的应用论文
- The road to learning English-Grammar
- 手机测试人员的思维过程
- matlab截视频人脸,一种视频图像中人脸图像截取方法与流程