RSA 暗号技術の基礎からC++による実装まで

2008年11月2日(更新)
2001年12月14日(公開)

表紙

このページはライター橋本晋之介の著作を紹介しています。また、本文や付属プログラムの誤りの訂正、よくあるご質問に対する回答などを掲載しています。

新着情報

2008年11月2日
訂正等を追加しました。

2002年8月12日
ZDNetの報道によると確定的素数判定法の決定的なアルゴリズムが開発されたようです。同ページから論文のPDFファイルがリンクされています。このアルゴリズムについての評価に関する情報がありましたら橋本までお教え下さい。

お知らせ

2003年2月20日現在、訂正が9点あります。

ページ内リンク [ 概要 | 訂正等 ]

概要

書名RSA 暗号技術の基礎からC++による実装まで
著者橋本晋之介(はしもと しんのすけ)
発行ソフトバンクパブリッシング
発行日2001年12月27日
ページ数211ページ
価格2,600円
ISBN4-7973-1702-7
内容暗号技術の基礎の解説。RSA暗号のサンプルプログラム付属。全ソースコード解説。CD-ROM付属(数値計算クラスライブラリ、RSA鍵生成/暗号化/復号化)
目次
  1. 暗号の理論とRSA暗号
  2. 実現方針
  3. 数学知識とアルゴリズム
  4. CMPIクラスとRSA暗号関数の設計
  5. CMPIクラスの実装
  6. RSA暗号関数の実装
  7. テストと利用例
  8. 信頼性を高めるために
  9. RSA暗号を取り巻く社会
  10. 付録:オープンな暗号システム Open PGP, SSL について

ページ内リンク [ 概要 | 訂正等 ]

訂正等

印刷・発行後に発見された誤りなどについて報告します。読者の皆様にお詫びいたします。また、ご連絡・ご指摘を下さった皆様にお礼を申し上げます。

P.171 ラビン法ソース L.5 コメント
2008.11.2

読者から「23は素数」とのご指摘をいただきました。その通りです。失礼いたしました。

// 試験数36個 9, 15, 21, 23, 25は素数ではない 他は素数

// 試験数36個 9, 15, 21, 25は素数ではない 他は素数

標準C++対応方法
2005.1.15

サンプルプログラムはVC++ 6.0で開発していますので、当時のANSI C++に準拠しています。VC++ .NET 2003は標準C++準拠ですので、名前空間の扱いが変更されています。以下の通り修正してください。

cmpi.cppの冒頭

#include <iostream> //<iostream.h>から変更
#include <iomanip> //追加
using namespace std; //追加

rsasample.cppの冒頭

#include <iostream> //<iostream.h>から変更
using namespace std; //追加

test.cppの冒頭

#include <iostream> //<iostream.h>から変更
using namespace std; //追加

P.119 5.3.3 最大公約数 CMPI gcd()
2003.2.20
2001.12.14

読者より訂正内容に誤りがあるとの指摘がありました。
CMPI gcd()において、本文では仮引数がconst & 宣言されていますが、付属CD-ROMのソースではconst & 宣言がありません。
付属CD-ROMのソースが正しいです。const & 宣言すると関数内で代入ができません。本文を訂正してください。

CMPI gcd(   // 結果
   const CMPI& a,   // 演算数1
   const CMPI& b )   // 演算数2
{
   :
   :
}

CMPI gcd(   // 結果
   CMPI a,   // 演算数1
   CMPI b )   // 演算数2
{
   :
   :
}

P.69 仕様
2002.9.3

暗号文を他の復号化プログラムに渡したところ、正常に復号化できないとのご指摘がありました。その方が調べたところ、CMPI::CMPI( const u_short* vi, const int li )で数値の格納語順が逆なためだとのご指摘を頂きました。
このコンストラクタは与えられたメモリ領域をそのまま使用しています。本サンプルプログラムでは暗号化・復号化の両方で同じ仕組みを使っているので問題ありませんが、一方に他のプログラムを使用される場合は、メッセージの構成などについて詳細に整合性を取る必要があります。この点説明が不十分でしたので、ここに記します。
他のプログラムと連携させる場合、RFC2440(付属CD-ROMにも収録)が参考になります。

P.38 ソース
2002.7.16
2002.7.10

読者から指摘がありました。添え字の範囲を示す定数の使い方が誤っていました。また、結果の取り出しと繰り上がり処理が本文と異なっていました。さらに、スペースの使い方でうまく表示できていない部分があることをご指摘いただきました。 以下の通り再訂正します。

   for( l = 0; l < m; l++ )
      c[l] = 0;   // 結果の初期化
   for( i = 0; i < n; i++ ){     // bの各桁について
      k = 0;     //繰り上がりの初期化
      for(j = 0; j < m; j++){     // aの各桁について
         s = a[j] * b[i] + c[i+j] +k;   // (*1)
         c[i+j] = s % UNIT;   // i+j桁目の結果(*2)
         k = s / UNIT;   // 繰り上がり
      }
      c[i+m] = k;   // 繰り上がり
   }

   *:UNITは基数。10進数ならUNITの値は10

   for( l = 0; l < n+m-1; l++ )
      c[l] = 0;   // 結果の初期化
   for( i = 0; i < m; i++ ){     // bの各桁について   訂正:m <- n
      k = 0;     //繰り上がりの初期化
      for(j = 0; j < n; j++){     // aの各桁について   訂正:n <- m
         s = a[j] * b[i] + c[i+j] +k;   // (*1)
         c[i+j] = s & MASK;   // i+j桁目の結果(*2)   訂正:(& MASK) <- (% UNIT)
         k = s >> LENGTH;   // 繰り上がり(*3)   訂正:(>> LENGTH) <- (/ UNIT)
      }
      c[i+m] = k;   // 繰り上がり
   }

   *2: MASKは1桁分を取り出すためのマスク   訂正
   *3: LENGTHは1桁分のビット数   追加

P.37 ソースL.6
2002.7.10

読者から指摘がありました。本文とソースが矛盾していますが、本文が正しいです。ソースを以下の通り訂正します。

   z[i] = UNIT - a[i] - t;     // (*)

   z[i] = UNIT + a[i] - t;     // (*)

P.140  ソース 下からL.8
P.144 ソース 下からL.6
2002.4.16

読者から「Release構成でメモリアクセスエラーが発生する」とのご指摘を頂きました。ご指摘の通り、要求メモリサイズが1桁分足りませんでした。以下の通り訂正します。付属CD-ROMのソースも修正してください。

   ce = (char*)new( char[e.getMaxColumn()*4+1] );
   cd = (char*)new( char[d.getMaxColumn()*4+1] );
   cn = (char*)new( char[n.getMaxColumn()*4+1] );

   ce = (char*)new( char[ (e.getMaxColumn()+1) *4+1] );
   cd = (char*)new( char[ (d.getMaxColumn()+1) *4+1] );
   cn = (char*)new( char[ (n.getMaxColumn()+1) *4+1] );

P.47  3.11 素数 L.14
2002.4.16

読者から「判定の範囲は3からその数の半分ではなくその数の平方根までで十分」とのご指摘を頂きました。また、「奇数で割るよりも素数で割った方が能率的」とのご指摘も頂きました。確かにその通りです。以下の通り訂正します。

理屈では、3からその数の半分までの奇数で割ってみて、余りが0なものが1つでもあれば素数ではありません。しかし、除算は速度の遅い計算ですし、256ビットで表せる数の半分とは2の256乗個もあります。繰り返し回数が多すぎてこの判定方法は使えません。

理屈では、3からその数の平方根までの既知の素数で割ってみて、余りが0なものが1つでもあれば素数ではありません。しかし、除算は速度の遅い計算ですし、256ビットで表せる数の平方根とは2の128乗個もあります。繰り返し回数が多すぎますし、それだけの素数表を作っておくこともたいへんです。この判定方法は使えません。

P.47 3.11 素数 L.1
2002.1.24

読者から「1は素数ではない」とのご指摘をいただきました。その通りです。失礼いたしました。

1,2,3,5,7,11などの数が素数です。

2,3,5,7,11などの数が素数です。

P.47 3.11 素数 L.4
2002.1.24

「素数の数」について読者からのご指摘を頂きました。参考文献(2)の「暗号理論入門」のP.15にも書かれていました。失礼しました。

素数が無限に存在するかどうかは証明されていませんが、経験的に無限に存在するといわれています。

素数は無限に存在することが証明されています。

P.115 5.3.1 ラビン法 ソース L.4,5
2002.1.24

上記のご指摘に伴い、ソースの一部を訂正します。お手数ですが、付属ソースプログラムを修正してください。

   if ( n == 0 ) return 0;      // 0は素数ではない
   if ( n == 1 || n == 2 ) return 1;   //  1,2は素数

   if ( n == 0 || n == 1 ) return 0;      // 0,1は素数ではない
   if ( n == 2 ) return 1;   //  2は素数

ページ内リンク [ 概要 | 訂正等 ]

おわりに

このページはフリーライター橋本晋之介(はしもとしんのすけ)が運営しています。
他にも誤りなどがあれば、お手数ですがご連絡ください。よろしくお願いいたします。

トップページに戻る