RSA算法原理与加密解密 求私钥等价求求模反元素 等价于分解出2个质数 (r*X+1)%[(p-1)(q-1)]=0...

 【

欧拉函数定义

注意不是整除,是存在只有为1的公约数

Euler's totient function - Wikipedia https://en.wikipedia.org/wiki/Euler%27s_totient_function

In number theoryEuler's totient function counts the positive integers up to a given integer n that are relatively prime to n. It is written using the Greek letter phi as φ(n) or ϕ(n), and may also be called Euler's phi function. It can be defined more formally as the number of integers k in the range 1 ≤ k ≤ n for which the greatest common divisor gcd(nk) is equal to 1.[2][3] The integers k of this form are sometimes referred to as totatives of n.

大于等于1但小于等于(此处包含与否不影响结果)n的正整数中与n的最大公约数为1的正整数的个数

注意,结果中包含1;

【1既不是质数(素数)但是1与所有正整数互质】

【最大公约数   Greatest common divisor  Greatest common divisor - Wikipedia https://en.wikipedia.org/wiki/Greatest_common_divisor 】

 

【小于等于p^k的数中,与p^k有非1公约数的正整数的公约数为且仅为p的若干次方,从0到k次方,最小的数为p,下一个为p*2,下一个为p*3、、、至p*p^(k-1),即p*i,i=1,2,3...,p^(k-1),故

总数p^k-扣除的个数p^(k-1)】

 

若p1和p2互质,n=p1*p2,则ψ(n)= ψ(p1*p2)= ψ(p1) ψ(p2)

【gcd(p1,j1i)=1 gcd(p2,j2i)=1  gcd(p1,p2)=1 

gcd(p1,j1i*j2i)=1 gcd(p2,j1i*j2i)=1

与p1互质的数与p2也互质,反之亦然

a b 均与p互质,则a*b也与p互质

故与p1*p2互质的数 为 (1,j1i)* (1,j2i) 

个数为个数的积】

 

 任意一个大于1的正整数都可以写成一系列质数的积

【算术基本定理 区别于 代数基本定理 见维基百科英文版】

 

因为

         n = (p1^k1)* (p2^k2)*……(pr^kr)   (p1~pr都是质数)

所以

         ψ(n)= ψ((p1^k1)) ψ(p2^k2) ……ψ(pr^kr)   定理4

         ψ(n)= (p1^k1)*(1-1/p1) * (p2^k2)(1-1/p2)……(pr^kr)*(1-1/pr)   定理3

         ψ(n)= (p1^k1)* (p2^k2)*……(pr^kr) * (1-1/p1) (1-1/p2)…… (1-1/pr)

         ψ(n)=n (1-1/p1) (1-1/p2)…… (1-1/pr)  

    【<n 且为正整数  

=[p1^(k1-1)*(p1-1)]*[p2^(k2-1)*(p2-1)]*...*[pr^(kr-1)*(pr-1)]

待证明

(三)  欧拉定理:

正整数a与n互质,则下式恒成立

a^ψ(n) ≡1(mod n)

 

Operation

The RSA algorithm involves four steps: key generation, key distribution, encryption and decryption.

A basic principle behind RSA is the observation that it is practical to find three very large positive integers e, d and n such that with modular exponentiation for all integers m (with 0 ≤ m < n):

【m^(ed)%n=m
m^(ed-1)%n=1
m、n互质
根据欧拉定理
ed-1可以至少可以取n的欧拉数

and that even knowing e and n or even m it can be extremely difficult to find d.

In addition, for some operations it is convenient that the order of the two exponentiations can be changed and that this relation also implies:

RSA involves a public key and a private key. The public key can be known by everyone, and it is used for encrypting messages. The intention is that messages encrypted with the public key can only be decrypted in a reasonable amount of time by using the private key. The public key is represented by the integers n and e; and, the private key, by the integer d (although n is also used during the decryption process. Thus, it might be considered to be a part of the private key, too). m represents the message (previously prepared with a certain technique explained below).

Key generation

The keys for the RSA algorithm are generated the following way:

  1. Choose two distinct prime numbers p and q.
    • For security purposes, the integers p and q should be chosen at random, and should be similar in magnitude but differ in length by a few digits to make factoring harder.[2] Prime integers can be efficiently found using a primality test.
  2. Compute n = pq.
    • n is used as the modulus for both the public and private keys. Its length, usually expressed in bits, is the key length.
  3. Compute λ(n) = lcm(λ(p), λ(q)) = lcm(p − 1, q − 1), where λ is Carmichael's totient function. This value is kept private.
  4. Choose an integer e such that 1 < e < λ(n) and gcd(eλ(n)) = 1; i.e., e and λ(n) are coprime.
  5. Determine d as d ≡ e−1 (mod λ(n)); i.e., d is the modular multiplicative inverse of e modulo λ(n).
  • This means: solve for d the equation de ≡ 1 (mod λ(n)).
  • e having a short bit-length and small Hamming weight results in more efficient encryption – most commonly e = 216 + 1 = 65,537. However, much smaller values of e (such as 3) have been shown to be less secure in some settings.[14]
  • e is released as the public key exponent.
  • d is kept as the private key exponent.

The public key consists of the modulus n and the public (or encryption) exponent e. The private key consists of the private (or decryption) exponent d, which must be kept secret. pq, and λ(n) must also be kept secret because they can be used to calculate d.

In the original RSA paper,[2] the Euler totient function φ(n) = (p − 1)(q − 1) is used instead of λ(n) for calculating the private exponent d. Since φ(n) is always divisible by λ(n) the algorithm works as well. That the Euler totient function can be used can also be seen as a consequence of the Lagrange's theorem applied to the multiplicative group of integers modulo pq. Thus any d satisfying de ≡ 1 (mod φ(n)) also satisfies de ≡ 1 (mod λ(n)). However, computing d modulo φ(n) will sometimes yield a result that is larger than necessary (i.e. d > λ(n)). Most of the implementations of RSA will accept exponents generated using either method (if they use the private exponent d at all, rather than using the optimized decryption method based on the Chinese remainder theorem described below), but some standards like FIPS 186-4 may require that d < λ(n). Any "oversized" private exponents not meeting that criterion may always be reduced modulo λ(n) to obtain a smaller equivalent exponent.

Since any common factors of (p − 1) and (q − 1) are present in the factorisation of n − 1 = pq − 1 = (p − 1)(q − 1) + (p − 1) + (q − 1),[15] it is recommended that (p − 1) and (q − 1) have only very small common factors, if any besides the necessary 2.[2][16][17]

Note: The authors of the original RSA paper carry out the key generation by choosing d and then computing e as the modular multiplicative inverse of d modulo φ(n). Since it is beneficial to use a small value for e (e.g., 65,537) in order to speed up the encryption function, current implementations of RSA, such as those following PKCS#1, choose e and compute d instead.[2][18]

Key distribution

Suppose that Bob wants to send information to Alice. If they decide to use RSA, Bob must know Alice's public key to encrypt the message and Alice must use her private key to decrypt the message. To enable Bob to send his encrypted messages, Alice transmits her public key (ne) to Bob via a reliable, but not necessarily secret, route. Alice's private key (d) is never distributed.

Encryption

After Bob obtains Alice's public key, he can send a message M to Alice.

【将明文转化为一个整数,可能对明文做截断处理,生成多个正整数,分段加密 string msg--->int m

by using an agreed-upon reversible protocol known as a padding scheme  通过双方约定好的字符串转整数算法

To do it, he first turns M (strictly speaking, the un-padded plaintext) into an integer m (strictly speaking, the padded plaintext), such that 0 ≤ m < n by using an agreed-upon reversible protocol known as a padding scheme. He then computes the ciphertext c, using Alice's public key e, corresponding to

This can be done reasonably quickly, even for 500-bit numbers, using modular exponentiation. Bob then transmits c to Alice.

Decryption

Alice can recover m from c by using her private key exponent d by computing

Given m, she can recover the original message M by reversing the padding scheme.

 

 

 

 

【因为求私钥,即求eKEY+1能被(p-1)(q-1)的整除的KEY,而e、p*q已被公开,故求私钥等价于分解p*q】

【e 与 n的欧拉数互质,一定存在 e对于n的欧拉数的模范元素,此处不要求e次小于n的欧拉数,

e 与 (p-1)(q-1)互质,一定存在 e对于 (p-1)(q-1)的模反元素,此处不要求e次小于 (p-1)(q-1),

记这个模反元素为d

即ed-1可以被(p-1)(q-1)整除,记商为ratio

则d=[(p-1)(q-1)*ratio+1]/e, 根据模反元素定义,ratio一定存在

 

(e*KEY-1)%[(p-1)(q-1)]=0

公钥(p-1)(q-1),e

私钥(p-1)(q-1),d

 

(r*X+1)%[(p-1)(q-1)]=0

 

【取2个不同的质数 p ,q(如果相同呢?),取小于p*q的质数r

根据欧拉定理

存在质数d使得e*d-1(或者d为r的欧拉数减少1次方)可以被p*q的欧拉数整除

存在质数d使得e*d-1可以被(p-1)(q-1)整除

 

【欧拉定理

Euler's theorem - Wikipedia https://en.wikipedia.org/wiki/Euler%27s_theorem

In number theoryEuler's theorem (also known as the Fermat–Euler theorem or Euler's totient theorem) states that if n and a are coprime positive integers, then

 

 

设正整数k, e*d = kψ(n)+1;

 

则ed-kψ(n)=1

  d = (kψ(n)+1) / e;

对于不定方程ax+by=c,设gcd(a,b)=d,如果ax+by=c有解,则d|c----->也就是说如果ed-kψ(n)=1 有解,则gcd(d,-k)能够整除1,而1显然可以被任何整数整除,所以该二元一次方程必定有解(d,k)

 

 (欧几里得定理和扩展欧几里得定理计算二元一次方程)

2)        将n和d封装成私钥

 

 

五、RSA算法可靠性论证

从上文可以统计出整个算法涉及到的量有6个,其中三个为由私钥持有者生成,三个是私钥持有者推导出来的

生成量:p,q,e

推导量:n, ψ(n),d

 

密钥中只有公钥被发布,所有人都可以获取。而公钥由n和e封装起来,因此,如果要破解一份RSA加密过的密文,我们必须使用私钥(私钥由n和d封装而成)

n可以从公钥获取。

 

(假设mc为明文,c为密文,则公钥由n和e封装则意味着求取密文的运算中,n,e和mc是已知数,只有c是未知数;私钥由n和d封装,同上,解密密文的运算中,n,d和c是已知的,只有mc是未知数。)

 

因此,破解私钥的关键就是破解e对于ψ(n)的模反元素d。

         其数学关系是:  e*d=1(modψ(n));

因此需需要先求出ψ(n),而求出ψ(n)需要知道ψ(p)和ψ(q)(因为ψ(n)= ψ(p* ψ(q))

 

而p和q只能通过分解n的质因数获得。所以,整个RSA算法都基于n这个大数不能分解质因数这个基础上。

        

因此,只要n够大,私钥就不会被破解

 

 

六、加解密过程:假设明文是m,c是密文

(一)  加密:使用公钥(n,e)

先将其换算成asc码或者unicode等其他数值。且m必须小于n

则加密算法是

         m^e=c(mod n)

推出

         m^e / n = k ……c这里c就是密文,k我们不关心

(二)  解密:使用私钥(n,d)

1.        简单的说解密就是通过下式求m。(一定可以求解出m)

c^d = m(mod n)

推出
c^d / n = k … … m    m就是明文编码,不关心k

 

查表得出明文

 

JAVA的非对称加密算法RSA——加密和解密 - 牵着妞去散步 - 博客园 https://www.cnblogs.com/OnlyCT/p/6586856.html

 

 

下面简单总结加密和解密的完整过程。

 

l  签名过程:

1.        A提取消息m的消息摘要h(m),并使用自己的私钥对摘要h(m)进行加密,生成签名s

2.        A将签名s和消息m一起,使用B的公钥进行加密,生成密文c,发送给B。

l  验证过程:

1.        B接收到密文c,使用自己的私钥解密c得到明文m和数字签名s

2.        B使用A的公钥解密数字签名s解密得到H(m).

3.        B使用相同的方法提取消息m的消息摘要h(m)

4.        B比较两个消息摘要。相同则验证成功;不同则验证失败。

复制代码
package com.joe.main;  
  
import java.io.*;  
import java.math.BigInteger;  
import java.util.ArrayList;  
  
/**
 * @Description Demo说明: 
 *              1、按照加密解密和签名验签的逻辑,编写简单的demo,不涉及java中继承的RSA相关类和Sigesture签名类 
 *              2、只能对数字和字母进行加密, 不涉及编码和解码问题 。 3、不做数字签名和验证了,涉及到提取信息摘要。 
 */  
public class EnAndDe {  
    private long p = 0;  
    private long q = 0;  
    private long n = 0;  
    private long t = 0; // 欧拉函数  
  
    private long e = 0; // 公匙  
    private long d = 0; // 密匙  
  
    private String mc; // 明文  
    private long c = 0; // 密文  
    private long word = 0; // 解密后明文  
  
    // 判断是一个数 x 否为素数素数就是判断在 (2,√x)范围内有没有除1外的因数,如果没有则x数素数  
    public boolean isPrime(long t) {  
        long k = 0;  
        k = (long) Math.sqrt((double) t);  
        for (int i = 2; i <= k; i++) {  
            if ((t % i) == 0) {  
                return false;  
            }  
        }  
        return true;  
    }  
  
    // 随机产生大素数(1e6数量级,注意,太大了要超出范围)  
    public void bigprimeRandom() {  
        do {  
            p = (long) (Math.random() * 1000000);  
        } while (!this.isPrime(p));  
        do {  
            q = (long) (Math.random() * 1000000);  
        } while (p == q || !this.isPrime(q));  
    }  
  
    // 输入PQ  
    public void inputPQ() throws Exception {  
  
        this.bigprimeRandom();  
        System.out.println("自动生成两个大素数p,q分别为:" + this.p + " " + this.q);  
  
        this.n = (long) p * q;  
        this.t = (long) (p - 1) * (q - 1);  
  
        System.out.println("这两个素数的乘积为p*q:" + this.n);  
        System.out.println("所得的t=(p-1)(q-1):" + this.t);  
    }  
  
    // 求最大公约数  
    public long gcd(long a, long b) {  
        long gcd;  
        if (b == 0)  
            gcd = a;  
        else  
            gcd = gcd(b, a % b);  
        return gcd;  
  
    }  
  
    // 生成公匙  
    public void getPublic_key() throws Exception {  
        do {  
  
            this.e = (long) (Math.random() * 100000);  
            // e满足 e∈(1, ψ(n))且e与ψ(n)最大公约数为1,即 e与t互质  
        } while ((this.e >= this.t) || (this.gcd(this.t, this.e) != 1));  
        System.out.println("生成的公钥为:" + "(" + this.n + "," + this.e + ")");  
    }  
  
    // 生成私钥 e*d=1(modψ(n))==> d = (kψ(n)+1) / e  
    public void getPrivate_key() {  
        long value = 1; // value 是e和d的乘积  
        outer: for (long k = 1;; k++) {  
            value = k * this.t + 1;  
            if ((value % this.e == 0)) {  
                this.d = value / this.e;  
                break outer;  
            }  
        }  
        System.out.println("产生的一个私钥为:" + "(" + this.n + "," + this.d + ")");  
    }  
  
    // 输入明文  
    public void getText() throws Exception {  
        System.out.println("请输入明文:");  
        BufferedReader stdin = new BufferedReader(new InputStreamReader(  
                System.in));  
        mc = stdin.readLine();  
  
    }  
  
    // 解密密文  
    public void pascolum() throws Exception {  
        this.getText();  
        System.out.println("输入明文为: " + this.mc);  
        // 加密  
        ArrayList cestr = new ArrayList();  
        for (int i = 0; i < mc.length(); i++) {  
            this.c = this.colum((long) mc.charAt(i), this.n, this.e);  
            cestr.add(c);  
        }  
        System.out.println("加密后所得的密文为:" + cestr);  
        // 解密  
        StringBuffer destr = new StringBuffer();  
        for (int j = 0; j < cestr.size(); j++) {  
            this.word = this.colum(Long.parseLong(cestr.get(j).toString()),  
                    this.n, this.d);  
            destr.append((char) word);  
        }  
        System.out.println("解密后所得的明文为:" + destr);  
  
    }  
  
    // 加密、解密计算  
    public long colum(long mc, long n, long key) {  
        BigInteger bigy = new BigInteger(String.valueOf(mc));  
        BigInteger bign = new BigInteger(String.valueOf(n));  
        BigInteger bigkey = new BigInteger(String.valueOf(key));  
        return Long.parseLong(bigy.modPow(bigkey, bign).toString());// 备注1  
    }  
  
    public static void main(String[] args) {  
        try {  
            EnAndDe t = new EnAndDe();  
            t.inputPQ();  
            t.getPublic_key();  
            t.getPrivate_key();  
            t.pascolum();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
}  
复制代码

备注1:modPow(a,b)是java类BigInteger中的一个方法,返回结果是:调用该方法的对象的a次幂,模b的结果

转载于:https://www.cnblogs.com/yuanjiangw/p/10108686.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值