【
歐拉函數定義
注意不是整除,是存在只有爲1的公約數
Euler's totient function - Wikipedia https://en.wikipedia.org/wiki/Euler%27s_totient_function
In number theory, Euler'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(n, k) 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*三、、、至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:
- 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.
- 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.
- Compute λ(n) = lcm(λ(p), λ(q)) = lcm(p − 1, q − 1), where λ is Carmichael's totient function. This value is kept private.
- Choose an integer e such that 1 < e < λ(n) and gcd(e, λ(n)) = 1; i.e., e and λ(n) are coprime.
- 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 d⋅e ≡ 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. p, q, 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 d⋅e ≡ 1 (mod φ(n)) also satisfies d⋅e ≡ 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 (n, e) 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 theory, Euler'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封裝成私鑰
5、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夠大,私鑰就不會被破解
6、加解密過程:假設明文是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說明: * 一、按照加密解密和簽名驗籤的邏輯,編寫簡單的demo,不涉及java中繼承的RSA相關類和Sigesture簽名類 * 二、只能對數字和字母進行加密, 不涉及編碼和解碼問題 。 三、不作數字簽名和驗證了,涉及到提取信息摘要。 */ 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的結果