引言

在现实世界中,每个人都有自己的密码。在各种系统中都有各类加密和解密的需求。 本文将详细介绍一下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的简明教程相关推荐

  1. 非对称加密之RSA算法

    非对称加密之RSA算法 1. RSA算法简述 2. 模型分析 3.代码实现 3.1 算法实现 3.2 测试代码 3.3 测试结果 4. 算法实现分析 5. 数据分段处理 该系列文章列表 1.网络及数据 ...

  2. java程序设计简明教程张晓龙_Java网络编程简明教程

    Java网络编程简明教程 网络编程 计算机网络相关概念 计算机网络是两台或更多的计算机组成的网络,同一网络内的任意两台计算机可以直接通信,所有计算机必须遵循同一种网络协议. 互联网 互联网是连接计算机 ...

  3. 一周极客热文:Java 8简明教程

    该教程将带领你一步一步地认识这门语言Java 8的新特性.通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复注解.看完这篇教程后,你还将对最新推出的API有一 ...

  4. java 大学简明教程_Simply-Java 《JAVA大学简明教程:实例程序设计》例子及习题源代码 - 下载 - 搜珍网...

    JAVA大学简明教程:实例程序设计/附书源代码/Tutorial01/MovingShapes/BoundedShape.class JAVA大学简明教程:实例程序设计/附书源代码/Tutorial0 ...

  5. Java Web 简明教程

    点此查看 所有教程.项目.源码导航 1. 前言 本教程用于介绍Java Web开发入门的方方面面,包括开发环境.工具.网页.Java.数据库等. 本教程写于2016年底,一些内容相对比较陈旧了,新版的 ...

  6. 对称加密、非对称加密、RSA、消息摘要、数字签名、数字证书与 HTTPS 简介

    文章目录 1.加密算法简介 1.1 对称加密(Symmetric Key Algorithms) 1.2 非对称加密(Asymmetric Key Algorithms) 1.3 非对称加密 RSA ...

  7. 图文结合彻底理解非对称加密、RSA原理及安全性(图文版)

    博主:爱码叔 个人博客站点: icodebook 公众号:漫话软件设计 专注于软件设计与架构.技术管理.擅长用通俗易懂的语言讲解技术.对技术管理工作有自己的一定见解.文章会第一时间首发在个站上,欢迎大 ...

  8. java程序设计简明教程答案张晓龙_java2简明教程部分课后复习题答案

    JAVA2 简明教程习题答案 第二章 课堂习题 : public class Main { public static void main(String[] args) { //initializat ...

  9. android java rsa加密_Android RSA与Java RSA加密不一样标准产生问题的解决方法

    最近作一个基于android的客户端,客户端与Java服务器 (MyEclipse自带的Tomcat服务器)的通讯须要实施安全方案.而本人是使用非对称密钥来对数据进行加密的,客户端用公钥加密,服务器用 ...

最新文章

  1. python正则表达regex_Python 正则表达式(RegEx)
  2. html sql注入_Web安全-SQL注入(sqli-lab)
  3. 如何在 Asp.Net Core 中 管理敏感数据
  4. 数据结构与算法--求1~n能组成的所有二叉搜索树的排列
  5. java开发一款坦克大战游戏
  6. 内网渗透,横向移动总结(mimikatz域控)
  7. php编译时出错make: *** [libphp5.la] Error 1
  8. 用java编写战舰 游戏吗_如何在Java中正确建模战舰游戏
  9. hiberante中get和load方法的区别
  10. 机器学习 - 贝叶斯网络
  11. 画图别存为png 透明_怎么样是使(PNG格式)图片背景透明
  12. 微信公众号起名字攻略:怎么给公众号取名字?
  13. python for循环求1到100的和_python如何计算1到100的和(用for循环)
  14. VC++6.0 用gSoap客户端访问WebService
  15. 两道小学生的题----1000: 梦里的难题、1002: 拳皇
  16. Linux 下 启动 Oracle
  17. DHCP 实现动态 IP 上网简析
  18. 外链屏蔽解除?QQ还是打不开淘宝、抖音链接
  19. 《当程序员的那些狗日日子》(五十六)步入正轨
  20. mac安装powerdesigner

热门文章

  1. android loadsvm raw,OpenCV机器学习:Android上利用SVM实现手写体数字识别
  2. uni-app实现微信小程序长按拍视频的功能
  3. 铁乐学Python_day05-字典dict
  4. OpenGL3D图形、旋转、纹理、键盘移动、光照、滤波、透明(完整)
  5. C++实现的基于α-β剪枝算法的井字棋游戏
  6. 机器学习系列(一), 监督学习和无监督学习
  7. 网络安全与计算机信息管理论文,计算机信息管理技术在网络安全的应用论文
  8. The road to learning English-Grammar
  9. 手机测试人员的思维过程
  10. matlab截视频人脸,一种视频图像中人脸图像截取方法与流程