Shor's Algorithm Proof
Algorithm 1
Let us say the element of the group , with an identity element of , has an order of . Then, the discrete logarithm problem can be solved in at most steps according to the following algorithm.
Step 1.
Step 2.
Create two lists and .
Step 3.
Find .
Step 4.
is the solution to .
Explanation
Fundamentally, if the element of the group has an order of , then the discrete logarithm problem can be solved in at most steps. That has an order of means that at least holds true. Hence, it is easy to verify that among , there exists a that satisfies .
The Shanks’ algorithm reduces this computational load down to . If it’s a discrete logarithm problem applied to cryptography, since would be a significantly large number, reducing the computation by more than half has a significant meaning.
The terms baby steps and giant steps come from the lists of made by multiplying and the lists of made by multiplying .
Proof
Part 1. Existence
We must show that holds true.
When is divided by , let the quotient be , and the remainder be . Then, it can be represented as .
Then, since , and it follows. Because of , , and because of , .
Part 2. Time Complexity
To find , the list must be sorted, and using the most appropriate comparison sorting algorithm, calculations are necessary.
Since ,
■
Code
Below is the implementation of Shank’s algorithm in R language. Prime factorization code and Order finding code were used.
prime = read.table("../attachment
/cfile8.uf@25411C3C5968BBE322F0D4.txt"); prime = prime[,1]
factorize<-function(p)
{
q=p
factors<-numeric(0)
i=1; j=1
while(q!=1)
{
if(q%%prime[i]) {i=i+1}
else
{
q<-q/prime[i]
factors[j]<-prime[i]
i=1
j=j+1
}
}
return(factors)
}
order<-function(g,p,h=1) #Calculate a order of g in modulo p
{
qe<-table(factorize(p-1))
qe<-rbind(as.numeric(names(qe)),qe)
divisor<-qe[1,1]^(0:qe[2,1])
if((length(qe)/2)==1) {return(qe[1,1]^qe[2,1])}
for(i in 2:(length(qe)/2)) {divisor=c(divisor%*%t(qe[1,i]^(0:qe[2,i])))}
for(i in divisor) {if((FPM(g,i,p))%%p==1) break;}
return(i)
}
shanks<-function(g,h,p)
{
N<-order(g,p)
n<-1+floor(sqrt(N))
gn<-FPM(g,-n,p) #gn := g^{-n}
x<-p
List\_1<-numeric(n+1)
List\_1[1]=1
for(i in 1:n) {List\_1[i+1]=(List\_1[i]*g)%%p}
List\_2<-numeric(n+1)
List\_2[1]=h
for(i in 1:n) {List\_2[i+1]=(List\_2[i]*gn)%%p}
for(i in 0:n+1) {
for(j in 0:n+1) {
if (List\_1[i]==List\_2[j]) {x[length(x)+1]<-((i-1)+(j-1)*n)}
}
}
return(min(x))
}
shanks(11,21,71)
FPM(11,37,71)
shanks(156,116,593)
FPM(156,59,593)
shanks(650,2213,3571)
FPM(650,319,3571)
The result of running the above code is as follows, and it was verified to work correctly through checking with exponentiation by squaring.
See also
Security algorithms utilizing the difficulty of the discrete logarithm problem
Attack algorithms for the discrete logarithm problem
- Shanks’ algorithm
- Pollard’s rho algorithm
- Conditions under which the discrete logarithm problem is easily solved
Hoffstein. (2008). An Introduction to Mathematical Cryptography: p80. ↩︎