网站首页 > 技术文章 正文
RSA加密算法 RSA公钥加密算法是1977年由Ron Rivest, Adi Shamir 和Leonard Adleman一起提出,RSA就是他们三人姓氏开头字母拼在一起组成的。RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,至今未被完全攻破。目前已被ISO推荐为公钥数据加密标准。
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,截止2017年被普遍认为是最优秀的公钥方案之一。
RSA公开密钥密码体制 所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。
根据密钥的使用方法,可以将密码分为对称密码和公钥密码
对称密码:加密和解密使用同一种密钥的方式
公钥密码:加密和解密使用不同的密码的方式,因此公钥密码通常也称为非对称密码。
RSA算法实现过程 RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。
以甲要把信息发给乙为例,首先确定角色:甲为加密者,乙为解密者。首先由乙随机确定一个KEY,称之为密匙,将这个KEY始终保存在机器B中而不发出来;然后,由这个 KEY计算出另一个KEY,称之为公匙。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给甲,甲收到公钥后,利用公钥对信息加密,并把密文通过网络发送到乙,最后乙利用已知的私钥,就对密文进行解码了。以上就是RSA算法的工作流程。
RSA算法实现过程为:
1、随意选择两个大的质数p和q,p不等于q,计算N=pq。
2、根据欧拉函数,不大于N且与N互质的整数個数為(p-1)(q-1)。
3、选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。
4、用以下这个公式计算d:d× e ≡ 1 (mod (p-1)(q-1))。
5、将p和q的记录销毁。
以上内容中,(N,e)是公钥,(N,d)是私钥。
RSA算法的应用 RSA的公钥和私钥是由KeyPairGenerator生成的,获取KeyPairGenerator的实例后还需要设置其密钥位数。设置密钥位数越高,加密过程越安全,一般使用1024位。如下代码:
[代码]java代码:
1 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
2 // 密钥位数
3 keyPairGen.initialize(1024);
公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
[代码]java代码:
1 // 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。
2 KeyPair keyPair = keyPairGen.generateKeyPair();
3 // 公钥
4 PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
5 // 私钥
6 PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
7 byte[] publicKeyData = publicKey.getEncoded();
8 byte[] privateKeyData = publicKey.getEncoded();
公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。通过byte[]可以再度将公钥或私钥还原出来。具体代码如下:
[代码]java代码:
01 // 通过公钥byte[]将公钥还原,适用于RSA算法
02 public static PublicKey getPublicKey(byte[] keyBytes) throws
03 NoSuchAlgorithmException,InvalidKeySpecException {
04 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
05 KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);
06 PublicKey publicKey = keyFactory.generatePublic(keySpec);
07 return publicKey;
08 }
09 // 通过私钥byte[]将公钥还原,适用于RSA算法
10 public static PrivateKey getPrivateKey(byte[] keyBytes) throws
11 NoSuchAlgorithmException,InvalidKeySpecException {
12 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
13 KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);
14 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
15 return privateKey;
16 }
在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:
[代码]java代码:01 // 打印公钥信息
02 public static void printPublicKeyInfo(PublicKey key){
03 RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
04 Log.d(MainActivity.TAG, “RSAPublicKey:”);
05 Log.d(MainActivity.TAG, “Modulus.length=” +
06 rsaPublicKey.getModulus().bitLength());
07 Log.d(MainActivity.TAG, “Modulus=” +
08 rsaPublicKey.getModulus().toString());
09 Log.d(MainActivity.TAG, “PublicExponent.length=” +
10 rsaPublicKey.getPublicExponent().bitLength());
11 Log.d(MainActivity.TAG, “PublicExponent=” +
12 rsaPublicKey.getPublicExponent().toString());
13 }
14
15 // 打印私钥信息
16 public static void printPublicKeyInfo(PrivateKey key){
17 RSAPrivateKey rsaPublicKey = (RSAPrivateKey) privateKey;
18 Log.d(MainActivity.TAG, “RSAPrivateKey:”);
19 Log.d(MainActivity.TAG, “Modulus.length=” +
20 rsaPrivateKey.getModulus().bitLength());
21 Log.d(MainActivity.TAG, “Modulus=” +
22 rsaPrivateKey.getModulus().toString());
23 Log.d(MainActivity.TAG, “PublicExponent.length=” +
24 rsaPrivateKey.getPrivateExponent().bitLength());
25 Log.d(MainActivity.TAG, “PublicExponent=” +
26 rsaPrivateKey.getPrivateExponent().toString());
27 }
由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:
[代码]java代码: 01 // 使用N、e值还原公钥
02 public static PublicKey getPublicKey(String modulus, String
03 publicExponent)
04 throws NoSuchAlgorithmException, InvalidKeySpecException {
05 BigInteger bigIntModulus = new BigInteger(modulus);
06 BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
07 RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
08 bigIntPrivateExponent);
09 KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);
10 PublicKey publicKey = keyFactory.generatePublic(keySpec);
11 return publicKey;
12 }
13
14 // 使用N、d值还原公钥
15 public static PrivateKey getPrivateKey(String modulus, String
16 privateExponent)
17 throws NoSuchAlgorithmException, InvalidKeySpecException {
18 BigInteger bigIntModulus = new BigInteger(modulus);
19 BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
20 RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
21 bigIntPrivateExponent);
22 KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);
23 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
24 return privateKey;
25 }
公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(String transformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:”DES/CBC/PKCS5Padding”或”DES”。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。
Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
[代码]java代码:
1 // 编码前设定编码方式及密钥
2 cipher.init(mode, key);
3 // 传入编码数据并返回编码结果
4 byte[] dataResult = cipher.doFinal(input);
Cipher.init(mode, key)方法中MODE指加密或解密模式,值为Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,参数key在加密时传入PublicKey,在解密时以PrivateKey传入。Cipher.doFinal(byte[] data)则是将待编码数据传入后并返回编码结果。为了将编码结果转为可读字符串,通常最后还使用BASE 64算法对最终的byte[]数据编码后显示给开发者。
SSL证书是HTTP明文协议升级HTTPS加密协议的重要渠道,是网络安全传输的加密通道。关于更多SSL证书的资讯,请关注数安时代(GDCA)。GDCA致力于网络信息安全,已通过WebTrust 的国际认证,是全球可信任的证书签发机构。GDCA专业技术团队将根据用户具体情况为其提供最优的产品选择建议,并针对不同的应用或服务器要求提供专业对应的HTTPS解决方案。
文章来源于https://www.trustauth.cn/baike/24298.html
猜你喜欢
- 2025-07-01 Java 如何加载带密码的 PCKS8 PEM 私钥
- 2025-07-01 犯罪啊 2.8万台路由器居然共用一把RSA密钥
- 2025-07-01 HTTPS全站加密时代 网宿推证书优选方案
- 2025-07-01 如何在 Windows 11 或 10 上使用 Winget 安装 OpenSSH
- 2025-07-01 网络篇:朋友面试之https认证加密过程
- 2025-07-01 如何安全管理SSH密钥以防止服务器被入侵
- 2025-07-01 在 Windows 10 上实现免密码 SSH 登录
- 2025-07-01 HTTPS的加密过程是怎样的?(https加密和解密的过程)
- 2025-07-01 Linux系统实现SSH安全免密登录的设置与管理
- 2025-07-01 Burpsuit插件开发之RSA加解密(burpsuite安装插件)
你 发表评论:
欢迎- 590℃几个Oracle空值处理函数 oracle处理null值的函数
- 583℃Oracle分析函数之Lag和Lead()使用
- 570℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 568℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 563℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 555℃【数据统计分析】详解Oracle分组函数之CUBE
- 540℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 536℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)