RSA加密算法是一种非对称加密算法,在公开密钥加密和电子商业中被广泛使用。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的

[1]

RSA 加密算法的可靠性源自于对于极大的整数做因数分解很难在有限的时间内得到有效的解,在未来的某一天,随着计算机性能的不断提高,RSA 算法的可靠性可能会降低,但是就目前的计算机来讲很难通过暴力的方式直接破解经过 RSA 算法加密之后的信息

数学基础

  • 互质关系

    对于两个正整数,如果这两个正整数除了 \(1\) 之外没有任何公因数,那么就将这两个数称为两者之间是 “互质” 的,比如,对于 \(7\) 和 \(12\),由于它们之间没有除了 \(1\) 之外的公因数,因此它们之间的关系就是 “互质” 的

    根据定义,可以得到以下的关系:

    1. 任意的两个质数将会构成 “互质” 关系
    2. 如果一个数是一个质数,那么只要另一个数不是前一个数的倍数,那么这两者之间将会构成 “互质” 关系
    3. 对于两个树,如果较大的那个数是质数,那么这两者之间同样构成 “互质“ 关系
    4. \(1\) 和任意的一个自然数都会构成 “互质” 关系
    5. 对于任意的大于 \(1\) 的整数 \(p\),那么 \(p\) 和 \(p - 1\) 将会构成 “互质” 关系
    6. 对于任意的大于 \(1\) 的整数 \(p\),如果 \(p\) 是一个奇数,那么 \(p\) 和 \(p - 2\) 将会构成 “互质” 关系
  • 欧拉函数 [4]

    在数论中,对于给定的任意正整数 \(n\),欧拉函数 \(\varphi(n)\) 表示小于等于 \(n\) 的正整数中与 \(n\) 互质的数的个数

    对于任意的正整数,都可以写成一系列质数的积,即:

    \[ n = p_1^{k_1}p_2^{k_2}……p_r^{k_r}\qquad(p_r 表示质数,k_r 表示出现相乘次数)
    \]

    此时,欧拉函数 \(\varphi(n)\) 的计算公式如下:

    \[ \begin{aligned}
    \varphi(n) &= p_1^{k_1 - 1} p_2^{k_2 - 1}……p_r^{k_r - 1}(p_1-1)(p_2-1)……(p_r-1) \\
    &=n(1 - \frac{1}{p_1})(1 - \frac{1}{p_2})……(1 - \frac{1}{p_r})
    \end{aligned}
    \]

    欧拉函数的积表示形式如下:

    \[ \varphi(mn) = \varphi(m)\varphi(n)\qquad (m, n 互质)
    \]

    特别地,对于 \(n\) 是质数的情况,有 \(\varphi(n) = n - 1\),这是因为当 \(n\) 是质数时,它和所有小于它的正整数都是 “互质” 的

    公式的证明请参考:https://zh.wikipedia.org/wiki/欧拉函数

  • 欧拉定理[2]

    如果两个正整数 \(a\) 和 \(n\) 互质,那么则有如下的等式成立:

    \[a^{\varphi(n)} \equiv 1\pmod{n}
    \]

    即:\(a\) 的 \(\varphi(n)\) 次方被 \(n\) 取余后剩 \(1\)​

  • 模反元素

    如果两个正整数 \(a\) 和 \(n\) 互质,那么一定可以找到整数 \(b\),使得 \(a*b - 1\) 被 \(n\) 整除,即:

    \[ab \equiv 1\pmod{n}
    \]

    此时 \(b\) 就被称为 \(a\) 的模反元素,这是由于

    \[a^{\varphi(n)} = a * a^{\varphi(n) - 1} \equiv 1\pmod{n}
    \]

    因此,\(a^{\varphi(n) - 1}\) 就是 \(a\) 的模反元素

算法原理

公钥和私钥

  1. 随意选择两个大的质数 \(p\) 和 \(q\),计算两者的积 \(N = p*q\)
  2. 根据上文提到的欧拉函数,求得 \(r = \varphi(N) = \varphi(p)*\varphi(q)=(p - 1)*(q - 1)\)​
  3. 选择一个小于 \(r\) 的正整数 \(e\),使得 \(e\) 和 \(r\) 互质,并求得 \(e\) 关于 \(r\) 的模反元素 \(d\)
  4. 删除 \(p\) 和 \(q\)

经过上述操作之后,得到的 \((N, e)\) 就被称之为公钥,而 \((N, d)\) 就被称之为私钥。一般会选择两个非常大的质数,经过操作之后会再将这两个数字进行转码,就是一般见到的存储形式x`

消息的加密

假如现在想要发送一个消息 \(m\) 到指定的地点,由于公钥是可见的,因此首先将 \(m\) 通过公钥 \((N, e)\) 转换为对应的整数(由于数据在计算机上都是通过二进制的方式存储的,可以以读取数字的方式读取信息),一般信息都会很长,因此会得到许多转换后的整数,具体单个整数的计算方式为:

\[c = m^e\bmod N
\]

消息的解密

每读取到一个整数 \(c\),通过下面的方式来进行解密:

\[m = c^d \bmod N
\]

得到 \(m\) 之后再对其进行对应的编码即可还原原来的信息

解密的原理:\(c^d = m^{ed} \bmod N\)

由于 \(e*d \equiv 1 \pmod r\)​,因此 \(e*d = 1 + h\varphi(N)\)​,则有:

\[m^{ed} = m^{1+h\varphi(N)} = m*m^{h\varphi(N)} = m*(m^{\varphi(N)})^h
\]
  • 如果 \(m\) 和 \(N\) 互质,那么

    \[m^{ed}= m*(m^{\varphi(N)})^h \equiv (1)^h\equiv m\pmod N
    \]
  • 如果 \(m\)​ 和 \(N\)​ 不是互质的,那么

    \(m\) 一定是 \(kp\) 或 \(kq\),假设 \(m\) 为 \(kp\) (为 \(kq\) 时同理),由于 \(p\) 和 \(q\) 都是质数,由互质关系 \(2\) 可得 \(kp\) 和 \(q\) 同样是互质关系。由欧拉公式,可以得到如下的关系:

    \[(kp)^{\varphi(q)}=(kp)^{q - 1}\equiv 1\pmod q
    \]

    进一步可得:

    \[[(kp)^{q - 1}]^{h(p-1)} = (kp)^{h\varphi(r)} \equiv 1 \pmod q
    \]

    此时,在等式两边同时乘上 \(kp\),可以得到如下关系:

    \[(kp)^{h\varphi(N)} * kp \equiv kp\pmod q
    \]

    由求模关系,可以得到如下等式:

    \[(kp)^{h\varphi(N) + 1}=(kp)^{ed} = tq + kp
    \]

    由于等式两边都是整数,并且 \(p\) 和 \(q\) 为不相等的质数,因此当等式两边同时除以 \(p\) 时,为了维护这个等式的成立,\(t\) 必须是 \(p\) 的整数倍。即 \(t = t'p\),进而等式变为:

    \[(kp)^{ed} = t'pq + kp
    \]

    由于 \(m=kp\),\(N=pq\),因此上述等式可以变为:

    \[m^{ed} = t'N + m
    \]

    因此 \(m^{ed} \equiv 1\pmod N\)

因此 \(m^{ed} \equiv m \pmod N\)

具体实现

由于 Java 存在 BigInteger 类来支持任意精度的数值计算,因此实现起来就会变得特别方便,具体实现代码如下所示:

static void test(String text) {
int BIT_LENGTH = 2048; Random rand = new SecureRandom();
BigInteger p = BigInteger.probablePrime(BIT_LENGTH / 2, rand);
BigInteger q = BigInteger.probablePrime(BIT_LENGTH / 2, rand);
// 计算 N
BigInteger n = p.multiply(q); // 计算 r
BigInteger phi = p.subtract(BigInteger.ONE)
.multiply(q.subtract(BigInteger.ONE)); BigInteger e = TWO; // 找到合适的 e
while (e.compareTo(phi) < 0) {
if (e.gcd(phi).intValue() == 1) break;
e = e.add(ONE);
} BigInteger d = e.modInverse(phi); // 获得 e 的模反元素 BigInteger msg = new BigInteger(text.getBytes(UTF_8)); // 将消息转换为对应的整数
BigInteger enc = msg.modPow(e, n); // 相当于对 msg 做 e 次乘法,再对 n 求模 System.out.println("raw=" + text);
System.out.println("enc=" + enc);
BigInteger dec = enc.modPow(d, n);
System.out.println("dec=" + new String(dec.toByteArray(), UTF_8));
}

假设现在输入的字符串为 “This is a simple text”,输出结果如下所示:

具体的,可以对编码后的数据进行特殊的处理,如:基于 16 位、基于 64 位 bit 的转换,就会变成常见的 key

参考:

[1] https://zh.wikipedia.org/wiki/RSA加密演算法

[2] https://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

[3] https://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

[4] https://zh.wikipedia.org/wiki/欧拉函数

RSA 加密算法的更多相关文章

  1. .net(c#)版RSA加密算法,拿走不谢

    今天有同学对接一个支付平台,涉及到RSA的签名和验签.由于对方是java的sdk,翻成c#语言时,搞了半天也没搞定.网上搜的东西都是各种copy还不解决问题. 碰巧,我之前对接过连连银通的网银支付和代 ...

  2. RSA加密算法的简单案例

    RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击. 那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例. 在使用数据集进行身份认证时,密码存在数据 ...

  3. RSA加密算法的java实现

    package rsa; import java.security.*;import java.security.interfaces.*;import javax.crypto.*; public ...

  4. 用实例讲解RSA加密算法(精)

    RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名.RSA以它的三个发明者Ron Rivest, Adi Shamir, Leonard Adleman的名字首字母命名,这个算法经 ...

  5. 关于RSA加密算法的长度限制问题

    RSA是常用的非对称加密算法.近来有学生在项目中使用System.Security类库中的RSA加密算法时,出现了“不正确的长度”,这实际上是因为待加密的数据超长所致..net Framework中提 ...

  6. RSA加密算法的加密与解密

    转发原文链接:RSA加密算法加密与解密过程解析 1.加密算法概述 加密算法根据内容是否可以还原分为可逆加密和非可逆加密. 可逆加密根据其加密解密是否使用的同一个密钥而可以分为对称加密和非对称加密. 所 ...

  7. 【python网络编程】使用rsa加密算法模块模拟登录新浪微博

    一.基础知识 http://blog.csdn.net/pi9nc/article/details/9734437 二.模拟登录 因为上学期参加了一个大数据比赛,需要抓取数据,所以就想着写个爬虫抓取新 ...

  8. 轻松学习RSA加密算法原理

    转自:http://blog.csdn.net/sunmenggmail/article/details/11994013 http://blog.csdn.net/q376420785/articl ...

  9. RSA加密算法原理及RES签名算法简介

    第一部分:RSA算法原理与加密解密 一.RSA加密过程简述 A和B进行加密通信时,B首先要生成一对密钥.一个是公钥,给A,B自己持有私钥.A使用B的公钥加密要加密发送的内容,然后B在通过自己的私钥解密 ...

  10. 浅谈RSA加密算法

    一.什么是非对称加密 1.加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加密 2.密钥分为:公钥,私钥  公钥:可以对外给任何人的加密和解密的密码,是公开的 私钥:通过私钥可以生成公钥,但从 ...

随机推荐

  1. 如何创建可引导的 macOS Sonoma 安装介质

    2023 年 9 月 26 日(北京时间 27 日凌晨)macOS Sonoma 正式版现已发布. 如何创建可引导的 macOS Sonoma 安装介质 如何创建可引导的 macOS 安装器 | 如何 ...

  2. pandas(进阶操作)-- 处理非数值型数据 -- 数据分析三剑客(核心)

    博客地址:https://www.cnblogs.com/zylyehuo/ 开发环境 anaconda 集成环境:集成好了数据分析和机器学习中所需要的全部环境 安装目录不可以有中文和特殊符号 jup ...

  3. Kubeflow基础知识

    kubeflow 基础知识 kubeflow 简介 kubeflow是谷歌开源的MLOps开源平台,其中包含的不同组件代表了机器学习生命周期的不同阶段. 下图是kubeflow组织ML工作流程: ku ...

  4. go语言 包依赖管理-构建完整的依赖项目:目录结构及包的调用

    目录结构: <home>/ |-- greetings/ |-- hello/1.分别进入对应目录创建以上目录结构 //bash切换到用户主目录 cd $HOMEPAHT$ //bash新 ...

  5. PostgreSQL学习笔记-5.基础知识:触发器、索引

    PostgreSQL 触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用. 下面是关于 PostgreSQL 触发器几个比较重要的点: PostgreSQL 触发器可以在BEFORE ...

  6. virsh domxxx命令

    1. 摘要信息类 1.1 dominfo 获取配置等摘要信息 [root@hyperhost ~]# virsh dominfo --domain centos7.6 Id: 1 Name: cent ...

  7. k8s-服务网格实战-配置 Mesh(灰度发布)

    在上一篇 k8s-服务网格实战-入门Istio中分享了如何安装部署 Istio,同时可以利用 Istio 实现 gRPC 的负载均衡. 今天我们更进一步,深入了解使用 Istio 的功能. 从 Ist ...

  8. tcpdump必知必会

    tcpdump原理 & 在tcp协议栈的位置 tcpdump用法 基于协议.主机.端口过滤 使用and or逻辑运算符做复杂的过滤操作 tcpdump flags 1. tcpdump原理 l ...

  9. 如何自学 PS、PR 等软件?

    学习Photoshop(PS)和Premiere Pro(PR)等软件需要一定的时间和耐心,以下是非常详细的自学指南. 第一部分:规划学习路线 1. 确定学习目标 在自学PS和PR之前,首先要明确自己 ...

  10. Alist手动安装并使用教程

    一.官方文档及下载地址 1.官方文档 AList文档 2.下载地址 alist · GitHub 二.下载并解压文件 以Windows为例,下载指定版本的文件. 三.运行 1.解压文件并进入文件夹: ...