I'm learning SageMath (uses Python 3)
and playing with the Goldbach conjecture.
I wrote this function (it works!):
def Goldbach(n):
if n % 2 != 0 or n <= 2:
show("No és parell")
else:
for i in srange(n):
if is_prime(i):
for j in srange(n):
if is_prime(j) and i + j == n:
a = [i, j]
show(a)
return
Now I'm trying (no idea) to do the following plot:
Denoting by r(2k) the number of Goldbach partitions of 2k,
the conjecture affirms that r(2k) > 0 if k > 1.
I have to do a graph of points (k, r(2k)), k > 2.
How could I do it?
First of all, let us get some better implementation in Sage
of the routine counting the number r(K) (for K > 2 some even integer) of the solutions for p + q = 2k, p, q prime numbers.
We count both solutions (p, q) and (q, p) when they differ.
def r(K):
if K not in ZZ or K <= 2 or K % 2:
return None
if K == 4:
return 1
count = 0
for p in primes(3, K):
for q in primes(3, K + 1 - p):
if p + q == K:
count += 1
return count
goldbach_points = [(K, r(K)) for K in range(4, 100,2)]
show(points(goldbach_points))
This gives:
How to calculate complexity of ths recursive algorithm?
int findMax(int a[ ], int l, int r)
{
if (r – l == 1)
return a[ l ];
int m = ( l + r ) / 2;
int u = findMax(a, l, m);
int v = findMax(a, m, r);
if (u > v)
return u;
else
return v;
}
From the Master Theorem:
T(n) = a * T(n/b) + f(n)
Where:
a is number of sub-problems
f(n) is cost of operation outside the recursion; f(n) = O(nc)
n/b size of the sub-problem
The idea behind this function is that you repeat the operation on the first half of items (T(n/2)) and on the second half of items (T(n/2)). You get the results and compare them (O(1)) so you have:
T(n) = 2 * T(n/2) + O(1)
So f(n) = O(1) and in terms of n value we get O(n0) - we need that to calculate c. So a = 2 and b = 2 and c = 0. From the Master Theorem (as correctly pointed out in comments) we end up with case where c < logba as log22 = 0. In this case the complexity of whole recursive call is O(n).
what is the fastest method to calculate this, i saw some people using matrices and when i searched on the internet, they talked about eigen values and eigen vectors (no idea about this stuff)...there was a question which reduced to a recursive equation
f(n) = (2*f(n-1)) + 2 , and f(1) = 1,
n could be upto 10^9....
i already tried using DP, storing upto 1000000 values and using the common fast exponentiation method, it all timed out
im generally weak in these modulo questions, which require computing large values
f(n) = (2*f(n-1)) + 2 with f(1)=1
is equivalent to
(f(n)+2) = 2 * (f(n-1)+2)
= ...
= 2^(n-1) * (f(1)+2) = 3 * 2^(n-1)
so that finally
f(n) = 3 * 2^(n-1) - 2
where you can then apply fast modular power methods.
Modular exponentiation by the square-and-multiply method:
function powerMod(b, e, m)
x := 1
while e > 0
if e%2 == 1
x, e := (x*b)%m, e-1
else b, e := (b*b)%m, e//2
return x
C code for calculating 2^n
const int mod = 1e9+7;
//Here base is assumed to be 2
int cal_pow(int x){
int res;
if (x == 0) res=1;
else if (x == 1) res=2;
else {
res = cal_pow(x/2);
if (x % 2 == 0)
res = (res * res) % mod;
else
res = (((res*res) % mod) * 2) % mod;
}
return res;
}
I have written myPercolation.ml.
open MyUnionFind
module type MyPercolationSig = sig
type percolation
val create_percolation : int -> percolation
val open_site : percolation -> int -> int -> unit
val is_open : percolation -> int -> int -> bool
val is_full : percolation -> int -> int -> bool
val can_percolates : percolation -> bool
end
module MyPercolation : MyPercolationSig = struct
exception IndexOutOfBounds;;
type percolation =
{n : int;
sites: bool array;
union : MyUnionFind.union_find};;
let create_percolation n =
{n = n; sites = Array.make (n*n) false; union = MyUnionFind.create_union (n*n)};;
let open_site p i j =
let {n;_;union} = p
in
if not (is_open p i j) then
begin
sites.(index_of n i j) <- true;
if i - 1 >= 1 && i - 1 <= n && is_open n (i-1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i-1) j)
else if i + 1 >= 1 && i + 1 <= n && is_open n (i+1) j then
MyUnionFind.union union (index_of n i j) (index_of n (i+1) j)
else if j - 1 >= 1 && j - 1 <= n && is_open n i (j-1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j-1))
else if j + 1 >= 1 && j + 1 <= n && is_open n i (j+1) then
MyUnionFind.union union (index_of n i j) (index_of n i (j+1))
end;;
let index_of n i j = n * (i - 1) + j;;
let is_open {n;sites;_} i j =
if i < 1 || i > n || j < 1 || j > n then
raise IndexOutOfBounds
else
sites.(index_of n i j);;
let is_full {n;_;union} i j =
let rec is_connected_top j' =
if j = 0 then false
else
if MyUnionFind.is_connected union (index_of n i j) (index_of n 0 j') then true
else is_connected_top (j'-1)
in is_connected_top n;;
let can_percolates p =
let {n;_;_} = p
in
let rec is_full_bottom j =
if j = 0 then false
else
if is_full p n j then true
else is_full_bottom (j-1)
end
Please ignore the package MyUnionFind package. It is just a homemade implementation for union-find algorithm.
when I try to compile the myPercolation.ml, I got such an error:
$ ocamlc -c myPercolation.ml
File "myPercolation.ml", line 25, characters 11-12:
Error: Syntax error: '}' expected
File "myPercolation.ml", line 25, characters 8-9:
Error: This '{' might be unmatched
I think the error is talking about let {n;_;union} = p in function of let open_site p i j.
I have read through that line and all code many times, but I still don't see any mismatched {} in that line.
can anyone help please?
Another possible error: {n;_;_} should be {n;_} Only 1 underscore is necessary. Think of it like the _ wildcard in a match statement.
The expression let {n; _; union} = p is not well formed OCaml. I think what you want is let {n; union} = p. The way to handle fields you don't care about in a record pattern is not to mention them.
Update:
As rgrinberg points out, a much better way to describe the problem is that the _ has to appear as the last field. That's why the compiler is expecting to see } afterward. It might be good style to include the _ as an indicator that you're purposely matching only a subset of the fields of the record. You can, in fact, turn on a compiler option that checks for this.
Update 2:
The warning for incomplete record patterns is warning number 9, and also is associated with the letter R. Here's how to use R:
$ ocaml -w +R
OCaml version 4.00.0
# type r = { a: int; b: char };;
type r = { a : int; b : char; }
# let {a} = {a=3; b='x'} in a;;
Warning 9: the following labels are not bound in this record pattern:
b
Either bind these labels explicitly or add '; _' to the pattern.
- : int = 3
The command-line syntax is the same for the compiler.
I have a RSA private key with modulus m, public exponent e and private exponent d, but the program I am using needs the modulus's prime factors p and q.
Is it possible to use e and d to get p and q?
Yes -- once you know the modulus N, and public/private exponents d and e, it is not too difficult to obtain p and q such that N=pq.
This paper by Dan Boneh describes an algorithm for doing so. It relies
on the fact that, by definition,
de = 1 mod phi(N).
For any randomly chosen "witness"
in (2,N), there is about a 50% chance of being able to use it to find a nontrivial
square root of 1 mod N (call it x). Then gcd(x-1,N) gives one of the factors.
You can use the open source tool I have developed in 2009 that converts RSA keys between the SFM format (n,e,d) and CRT format (p,q,dp,dq,u), and the other way around. It is on SourceForge : http://rsaconverter.sourceforge.net/
The algorithm I implemented is based on ideas presented by Dan Boneh, as described by the previous answer.
I hope this will be useful.
Mounir IDRASSI - IDRIX
I posted a response on the crypto stack exchange answering the same question here. It uses the same approach as outlined in Boneh's paper, but does a lot more explanation as to how it actually works. I also try to assume a minimal amount of prior knowledge.
Hope this helps!
I put in the effort to dig through Boneh's paper. The "algorithm" for deriving (p, q) from (n, d) is buried at the end of §1.1, coded in maths jargon, and left as an exercise for the reader to render out of his (rather terse) proof that it's efficient to do so.
Let 〈N, e〉 be an RSA public key. Given the private key d, one can efficiently factor the modulus N = pq.
Proof. Compute k = de − 1. By definition of d and e we know that k is a multiple of φ(N). Since φ(N) is even, k = 2tr with r odd and t ≥ 1. We have gk = 1 for every g ∈ ℤN×, and therefore gk/2 is a square root of unity modulo N. By the Chinese Remainder Theorem, 1 has four square roots modulo N = pq. Two of these square roots are ±1. The other two are ±x where x satisfies x = 1 mod p and x = −1 mod q. Using either one of these last two square roots, the factorization of N is revealed by computing gcd(x − 1, N). A straightforward argument shows that if g is chosen at random from ℤN× then with probability at least 1/2 (over the choice of g) one of the elements in the sequence gk/2, gk/4, …, gk/2t mod N is a square root of unity that reveals the factorization of N. All elements in the sequence can be efficiently computed in time O(n3) where n = log2(N).
Obviously, this is pretty close to meaningless for anyone who doesn't know what $Z_N^\ast$ is, and has a pretty nonlinear structure that takes a good deal of time to twist into a linear algorithm.
So here is the worked solution:
from random import randrange
from math import gcd
def ned_to_pqe(secret_key):
"""
https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf#:~:text=Given%20d%2C,reveals%20the%20factorization%20of%20N%2E
"""
n, e, d = secret_key
k = d * e - 1
t = bit_scan1(k)
trivial_sqrt1 = {1, n - 1}
while True:
g = randrange(2, n - 1)
for j in range(1, t + 1):
x = pow(g, k >> j, n)
if pow(x, 2, n) == 1:
if x in trivial_sqrt1: continue
p = gcd(x - 1, n)
q = n // p
if q > p: p, q = q, p
return p, q, e
def pqe_to_ned(secret_key):
p, q, e = secret_key
n = p * q
l = (p - 1) * (q - 1)
d = pow(e, -1, l)
return n, e, d
def bit_scan1(i):
"""
https://gmpy2.readthedocs.io/en/latest/mpz.html#mpz.bit_scan1
"""
# https://stackoverflow.com/a/63552117/1874170
return (i & -i).bit_length() - 1
def test():
secret_key = (
# https://en.wikipedia.org/wiki/RSA_numbers#RSA-100
# Should take upwards of an hour to factor on a consumer desktop ca. 2022
1522605027922533360535618378132637429718068114961380688657908494580122963258952897654000350692006139,
65537,
1435319569480661473883310243084583371347212233430112391255270984679722445287591616684593449660400673
)
if secret_key != pqe_to_ned(ned_to_pqe(secret_key)):
raise ValueError
if __name__ == '__main__':
test()
print("Self-test OK")
Live demo (JS):
function ned_to_pqe({n, e, d}) {
// https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf#:~:text=Given%20d%2C,reveals%20the%20factorization%20of%20N%2E
let k = d * e - 1n;
let t = scan1(k);
let trivial_sqrt1 = new Set([1n, n - 1n]);
while (true) {
let g = insecure_randrange(2n, n - 1n);
for ( let j = t ; j > 0 ; --j ) {
let x = bn_powMod(g, k >> j, n);
if (bn_powMod(x, 2n, n) === 1n) {
if (trivial_sqrt1.has(x)) continue;
let p = gcd(x - 1n, n), q = n/p;
if (q > p) [p, q] = [q, p];
return {p, q, e};
}
}
}
}
function pqe_to_ned({p, q, e}) {
let n = p * q;
let l = (p - 1n) * (q - 1n);
let d = bn_modInv(e, l);
return {n, e, d};
}
function bn_powMod(x, e, m) {
// h/t https://umaranis.com/2018/07/12/calculate-modular-exponentiation-powermod-in-javascript-ap-n/
if (m === 1n) return 0n;
let y = 1n;
x = x % m;
while (e > 0n) {
if (e % 2n === 1n) //odd number
y = (y * x) % m;
e = e >> 1n; //divide by 2
x = (x * x) % m;
}
return y;
}
function bn_modInv(x, m) {
// TOY IMPLEMENTATION
// DO NOT USE IN GENERAL-PURPOSE CODE
// h/t https://rosettacode.org/wiki/Modular_inverse#C
let m0 = m, t, q;
let x0 = 0n, y = 1n;
if (m === 1n) return 1n;
while (x > 1n) {
q = x / m;
t = m;
m = x % m;
x = t;
t = x0;
x0 = y - q * x0;
y = t;
}
if (y < 0n) y += m0;
return y;
}
function gcd(a, b) {
// h/t https://stackoverflow.com/a/17445304/1874170
while (b) {
[a, b] = [b, a % b];
}
return a;
}
function scan1(i) {
// https://gmplib.org/manual/Integer-Logic-and-Bit-Fiddling#mpz_scan1
let k = 0n;
if ( i !== 0n ) {
while( (i & 1n) === 0n ) {
i >>= 1n;
k += 1n;
}
}
return k;
}
function insecure_randrange(a, b) {
// h/t https://arxiv.org/abs/1304.1916
let numerator = 0n;
let denominator = 1n;
let n = (b - a);
while (true) {
numerator <<= 1n;
denominator <<= 1n;
numerator |= BigInt(Math.random()>1/2);
if (denominator >= n) {
if (numerator < n)
return a + numerator;
numerator -= n;
denominator -= n;
}
}
}
<form action="javascript:" onsubmit="(({target:form,submitter:{value:action}})=>{eval(action)(form)})(event)">
<p>
<label for="p">p=</label><input name="p" value="37975227936943673922808872755445627854565536638199" /><br />
<label for="q">q=</label><input name="q" value="40094690950920881030683735292761468389214899724061" /><br />
<label for="n">n=</label><input name="n" /><br />
<label for="e">e=</label><input name="e" placeholder="65537" /><br />
<label for="d">d=</label><input name="d" /><br />
</p>
<p>
<button type="submit" value="pqe2nd">Get (n,d) from (p,q,e)</button><br />
<button type="submit" value="delpq">Forget (p,q)</button><br />
<button type="submit" value="ned2pq">Get (p,q) from (n,e,d)</button>
</form>
<script>
function pqe2nd({elements}) {
if (!elements['e'].value) elements['e'].value = elements['e'].placeholder;
let p = BigInt(elements['p'].value||undefined);
let q = BigInt(elements['q'].value||undefined);
let e = BigInt(elements['e'].value||undefined);
let {n, d} = pqe_to_ned({p,q,e});
elements['n'].value = n.toString();
elements['d'].value = d.toString();
}
function ned2pq({elements}) {
if (!elements['e'].value) elements['e'].value = elements['e'].placeholder;
let n = BigInt(elements['n'].value||undefined);
let e = BigInt(elements['e'].value||undefined);
let d = BigInt(elements['d'].value||undefined);
let {p, q} = ned_to_pqe({n,e,d});
elements['p'].value = p.toString();
elements['q'].value = q.toString();
}
function delpq({elements}) {
elements['p'].value = null;
elements['q'].value = null;
}
</script>
To answer the question as-stated in the title: factoring N entails finding N. But you cannot, in the general case, derive N from (e, d). Therefore, you cannot, in the general case, derive the factors of N from (e, d); QED.
finding n from (e, d) is computationally feasible with fair probability, or even certainty, for a small but observable fraction of RSA keys of practical interest
If you want to try to do so anyway, you'll need to be able to factorize e * d - 1 (if I understand the above-linked answer correctly):
from itertools import permutations
def ed_to_pq(e, d):
# NOT ALWAYS POSSIBLE -- the number e*d-1 must be small enough to factorize
# h/t https://crypto.stackexchange.com/a/81620/8287
factors = factorize(e * d - 1)
factors.sort()
# Unimplemented optimization:
# if two factors are larger than (p * q).bit_length()//4
# and the greater of (p, q) is not many times bigger than the lesser,
# then you can safely assume that the large factors belong to (p-1) and (q-1)
# and thereby reduce the number of iterations in the following loops
# Unimplemented optimization:
# permutations are overkill for this partitioning scheme;
# a clever mathematician could come up with something more efficient
# Unimplemented optimization:
# prune permutations based on "sanity" factor of logarithm knapsacking
l = len(factors)
for arrangement in permutations(factors):
for l_pm1 in range(1, l - 1):
for l_qm1 in range(1, l_pm1):
pm1 = prod(arrangement[:l_pm1])
qm1 = prod(arrangement[l_pm1:l_pm1+l_qm1])
try:
if pow(e, -1, pm1 * qm1) == d:
return (pm1 + 1, qm1 + 1)
except Exception:
pass
from functools import reduce
from operator import mul
def prod(l):
return reduce(mul, l)