logo

ショアのアルゴリズムの証明 📂整数論

ショアのアルゴリズムの証明

アルゴリズム 1

単位元がeeであるグループGGの元ggが、オーダーNNとする。それならば、離散対数問題gx=hg^{x} = hは次のアルゴリズムに従って、多くてもO(NlogN)O \left( \sqrt{N} \log N \right)ステップ以内に解ける。


ステップ 1.

n:=1+Nn: = 1 + \lfloor \sqrt{N} \rfloor


ステップ 2.

二つのリストA:={e,g,g2,,gn}A := \left\{ e , g , g^{2} , \cdots , g^{n} \right\}B:={h,hgn,hg2n,,hgn2}B := \left\{ h , hg^{-n} , hg^{-2n} , \cdots , hg^{-n^2} \right\}を作る。


ステップ 3.

gi=hgjnABg^{i} = h g^{-jn} \in A \cap Bを見つける。


ステップ 4.

x=i+jnx = i + jngx=hg^{x} = hの解である。

説明

基本的にグループGGの元ggがオーダーNNである場合、離散対数問題gx=hg^{x} = hは多くてもO(N)O (N) ステップ以内に解ける。ggがオーダーNNであるとは、少なくともgN=eg^{N} = eが成り立つことを意味する。したがって、0,1,,N1 0, 1, \cdots , N-1の中にはgx=hg^{x} = hを満たすxxが存在することが簡単に確認できる。

シャンクスのアルゴリズムは、この計算量をO(NlogN)O \left( \sqrt{N} \log N \right)まで落としてくれる。暗号に適用される離散対数問題であれば、NNはかなり大きな数であろうから、半分以上計算を減らすことができるので、大きな意味がある。

ベビーステップとジャイアントステップは、ggを掛けて作られるリストAAと、gng^{-n}を掛けて作られるリストBBから出た言葉だ。

証明

パート 1. 存在性

(AB)\left( A \cap B \right) \ne \emptysetであることを示さなければならない。

xxnnで割った商をqq、余りをrrとすると、x=nq+rx = nq + rのように表せる。

するとN<n\sqrt{N} < nなので q=xrn<Nn<n q = {{ x - r } \over { n }} < {{ N } \over { n }} < n そして gx=h    gnq+r=h    gr=hgnq \begin{align*} & g^{x} = h \\ \implies & g^{ nq + r } = h \\ \implies & g^{ r } = h g^{ - nq } \end{align*} である。r<nr < nなのでgrAg^{r} \in Aであり、q<nq < nなのでhgnqBh g^{ - nq } \in Bである。


パート 2. 時間複雑性

ABA \cap Bを見つけるためにはリストをソートする必要があり、最適な比較ソートアルゴリズムを使用するとO(nlogn)O ( n \log n )回の計算が必要である。

nNn \approx \sqrt{N}であるため、 O(nlogn)=O(NlogN)=O(12NlogN)=O(NlogN) \begin{align*} O \left( n \log n \right) =& O \left( \sqrt{N} \log \sqrt{N} \right) \\ =& O \left( {{1} \over {2}} \sqrt{N} \log N \right) \\ =& O \left( \sqrt{N} \log N \right) \end{align*}

コード

以下は、R言語で実装されたシャンクスのアルゴリズムである。素因数分解コードオーダーを求めるコードが使用された。

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)

上記コードを実行した結果は以下の通りであり、連続べき乗法で検算して、正しく動作していることを確認した。

20190227\_100325.png

も参照

離散対数問題の難しさを利用したセキュリティアルゴリズム

離散対数問題に対する攻撃アルゴリズム


  1. Hoffstein. (2008). 「数学的暗号化への導入」: p80。 ↩︎