C ++楕円曲線暗号化アルゴリズム

  楕円曲線アルゴリズム
  
  :楕円曲線暗号は、楕円曲線の研究に由来する、ワイエルシュトラスと呼ばれる楕円曲線(ワイエルシュトラス)式を指し、
  
  Y2 = X3 + a1xy + A3Y A4X + A6 + a2x2 +(1)
  
  の平面曲線を決定します。係数ai(I = 1,2、...、6)は、有理数フィールド、実数フィールド、複素数フィールド、または楕円曲線暗号システムで使用される有限体GF(pr)である特定のフィールドで定義されます。楕円曲線はすべて有限体で定義されます。
  
  楕円曲線上のすべての点と、定義された加算演算と一緒に設定された無限点と呼ばれる特別な点は、Abelグループを構成します。方程式
  
  mP = P + P + ... + P = Q(2)
  
  では、mとポイントPでポイントQを見つけるのは比較的簡単ですが、ポイントQとポイントPでmを見つけることは非常に困難です。この問題は楕円曲線上の点群の離散対数問題。楕円曲線暗号システムは、この難しい問題を使用して設計されています。
  
  公開鍵アルゴリズムは、数学関数(一方向トラップドア関数など)に基づいています。公開鍵暗号システムは、一般に、それらが基づいている問題に従って、大きな整数分解問題クラス、離散対数問題クラス、および楕円曲線クラスの3つのカテゴリに分類されます。
  
  この記事は、Menezes-Vanstone楕円暗号化アルゴリズムの形の素数領域Zpに関するものです。
  
  素体の曲線関数は
  
  y ^ 2 = x ^ 3 + a * x + baであり、bはpより小さい非負の数であり
  
  、素数体の場合は4 * a ^ 3 + 27 * b ^ 2!= 0 ですさらに、すべての点P、QはE(Zp)に属し、追加ルールがあります
  
  .1。P + O = O + P = P、P +(-P)= O;
  
  Oは楕円曲線上のゼロ点または無限大と呼ばれる点ですが、Oは楕円曲線の追加領域上にあります。
  
  2.分配比と加算の結合法則、sの場合、tはZpに属し、(s + t)* P = s * P + t * Pがあり
  
  ます。3。P =(x1、y1)、Q =(x2、 y2)、およびP!= -Q、次にP + Q =(x3、y3)、
  
  x3 = k ^ 2-x1 -x2;
  
  y3 = k *(x1-x3)-y1 ;
  
  k =(y2-y1) /(x2-x1)if P!= Q;
  
  k =(3x1 ^ 2 + a)/(2 * y1)if P == Q;
  
  素数領域上の楕円曲線の除算は除算を使用し、除算の規則axb ^ -1 = c mod pを計算するのはa / b = c mod pです。ここで、b ^ -1はbの乗法逆数、つまりbxb ^ -1 = 1 mod pです。乗法逆数の場合、bとpが素数の場合、pが素数で、bが1にできない一意の解があります。乗算の逆を見つけるために、次のようにユークリッドアルゴリズムが一般的に使用されます:
  
  int getX_1(int x、int mod){
  
  int Q、X1、X2、X3、Y1、Y2、Y3、T1、T2、T3;
  
  X1 = 1 ;
  
  X2 = 0;
  
  X3 = mod;
  
  Y1 = 0;
  
  Y2 = 1;
  
  Y3 =(x%mod + mod)%mod; //
  
  (Y3!= 1){
  
  Q = X3 / Y3;
  
  T1 = X1-Q * Y1;
  
  T2 = X2-Q * Y2;
  
  T3 = X3-Q * Y3;
  
  X1 = Y1;
  
  X2 = Y2;
  
  X3 = Y3;
  
  Y1 = T1;
  
  Y2 = T2;
  
  Y3 = T3;
  
  }
  
  return Y2;
  
  }
  
  乗算ルール:
  
  1. kがZpに属している場合、 k * P = P + ..... + P(k Psの加算)
  
  2.任意のsについて、tはZpに属し、s *(t * P)=(s * t)* P
  
  はMenezes-Vanstone楕円暗号化アルゴリズム:
  
  1.鍵を生成
  
  し、秘密鍵として整数k、0 <k <pを選択し、曲線上の点Aを選択し、B = k * Aを計算します。公開鍵は(A ,, B)。このうち、Aはベースキーとも呼ばれます。n* A = Oとなる最小の整数nの場合、nはピリオドと呼ばれます。ピリオドが素数で大きな値であれば合理的です。
  
  2.暗号化プロセス:
  
  プレーンテキストをM =(​​m1、m2)とすると、Mは曲線E上の点ではない可能性があります。暗号文(C1、C2)が計算され、そのいずれかがZpに属する:
  
  C1 = r * A ;;
  
  Y =(y1、y2)= r * B;
  
  C2 =(C21、C22)=(y1 * m1 mod p、y2 * m2 mod p)
  
  3復号化プロセス。
  
  Z =(z1、z2)= k * C1を計算します。プレーンテキストM =(C21 * z1 ^ -1 mod p、C22 * z2 ^ -1 mod p)を計算します。
  
  負の数がある場合、c ++でのモジュラー演算は実行できません正しい結果は、vs2012でテストすると-1%2などの単なるピットであり、1ではなく-1を返します。c++でのモジュロ演算の結果の符号は、被除数の符号と同じです。
  
  パラメータの選択:p = 127を選択し、曲線関数は次のとおりです:y ^ 2 = x ^ 3 + 5 * x + 37、a = 5、b = 37、r =7。秘密鍵k = 9を選択し、点Aを( 11,4)次にB = k * A =(120,41)
  
  、ソースコードは次のとおりです。ここでは、charは直接暗号化されていますが、効果は良くありません
  
  #include "stdafx.h"
  
  #include <string>
  
  #include <iostream>
  
  using namespace std;
  
  const int k = 9;
  
  const int a = 5;
  
  const int b = 37;
  
  const int p = 127;
  
  const int r = 7;
  
  int getX_1(int x、int mod){
  
  int Q、X1、X2、X3 、Y1、Y2、Y3、T1、T2、T3;
  
  X1 = 1;
  
  X2 = 0;
  
  X3 = mod;
  
  Y1 = 0;
  
  Y2 = 1;
  
  Y3 =(x%mod + mod)%mod; //获得正整数
  
  while(Y3!= 1){
  
  Q = X3 / Y3;
  
  T1 = X1-Q * Y1;
  
  T2 = X2-Q * Y2;
  
  T3 = X3-Q * Y3;
  
  X1 = Y1;
  
  X2 = Y2;
  
  X3 = Y3;
  
  Y1 = T1;
  
  Y2 = T2;
  
  Y3 = T3;
  
  }
  
  Y2を返します。
  
  } //获得其乗法逆元
  
  struct point {
  
  int x;
  
  int y;
  
  };
  
  point A、B; //公钥
  
  typedef pair <point、point> twopoint;
  
  bool演算子==(point pa、point pb){
  
  return pa.x == pb.x && pa.y == pb.y;
  
  }
  
  ポイント演算子+(ポイントpa、ポイントpb){
  
  int k;
  
  if(pa == pb)
  
  k =((3 * pa.x * pa.x + a)* getX_1(2 * pa.y、p))%p; //正の整数を使用する必要があります。ここでは、pa.yの値を0にすることはできません。// 0の
  
  場合、pa = -pbであるため、この計算は実行できません。ただし、この結果はOであり、楕円曲線上にないため出力できません。
  
  //ここに期間番号があります。最初に簡単に指定できる基本値の場合、期間nがあるため、nA = Oであり、ここですべてのパラメータの選択された値は
  
  n未満です、それがOに到達しないように、それがうまくいかないことを確実にするために、それはこのようでなければなりません。
  
  そうでなければ
  
  k =(pb.y-pa.y)* getX_1(pb.x-pa.x、p)%p;
  
  ポイントc;
  
  cx =(k * k-pa.x -pb.x)%p;
  
  cy =(k *(pa.x-cx)-pa.y)%p;
  
  cx =(cx + p)%p;
  
  cy =(cy + p)%p;
  
  return c;
  
  }
  
  ポイント演算子*(point&b、 int n){
  
  point q = b;
  
  n = n -1;
  
  for(int i = 1; i <n; i ++){
  
  q = q + b;
  
  }
  
  return q;
  
  }
  
  twopoint ECodePoint(point m){
  
  point c1、c2;
  
  c1 = A * r;
  
  point Y = B * r;
  
  c2.x = Yx * mx%p;
  
  c2.y = Yy * my%p;
  
  return twopoint(c1、 c2);
  
  }
  
  point DCodePoint(twopoint t){
  
  point Z = t.first * k;
  
  point m;
  
  mx = t.second.x * getX_1(Zx、p)%p;
  
  my = t.second.y * getX_1( Zy、p)%p;
  
  return m;
  
  }
  
  string ECode(string input){//プレーンテキストの入力は文字列型ですが、単一の操作は、単一の文字から変換されたint型を計算する必要がありますchar
  
  string output = " ";
  
  ポイントM;
  
  2 ポイントC;
  
  for(int i = 0; i <input.length(); i ++){
  
  Mx = i;
  
  My = input [i];
  
  C = ECodePoint(M);
  
  出力+ =(char)C.first.x;
  
  出力+ =(char)C.first.y;
  
  出力+ =(char)C.second.x;
  
  出力+ =(char)C.second.y;
  
  }
  
  出力を返します。
  
  }
  
  string DCode(string input){
  
  string output = "";
  
  ポイントM;
  
  2点C;
  
  if(input.length()%4!= 0)は
  
  "入力"を返します; //結果として、暗号文肯定は4の倍数、そうでない場合は、肯定出力がわかります。for
  
  (int i = 0; i <input.length( );){
  
  C.first.x = input [i ++];
  
  C.first.y = input [i ++];
  
  C.second.x = input [i ++];
  
  C.second.y = input [i ++];
  
  M = DCodePoint(C);
  
  出力+ =(char)My;
  
  }
  
  出力を返します。
  
  }
  
  int main()
  
  {
  
  Ax = 11;
  
  Ay = 4;
  
  B = A * k;
  
  string s = "";
  
  //暗号化は簡単で、何かを入力するだけで暗号化できますが、復号化は機能しません。それを入力するのは間違いです
  
  。//プログラムは間違いなく失敗します。したがって、以前に暗号化された結果の復号化のみがサポートされます。
  
  cout << "メネゼス-ヴァンストーンアルゴリズムを使用して、素数フィールドで曲線y ^ 2 = x ^ 3 + 5 * x +37を使用:" << endl;
  
  素数フィールドでcout << "p = 127、privateキーはk = 9、公開キーA(11、4)、B(120、41)です。プレーンテキスト文字列は、暗号化のために直接intに変換されます "<< endl;
  
  cout <<"暗号化するコンテンツを入力してください: "< <endl;
  
  cin >> s;
  
  cout << "暗号文は次のとおりです:" << "\ r \ n";
  
  s = ECode(s);
  
  cout << s << endl;
  
  cout << "前の暗号文を復号化する、プレーンテキストは次のとおりです(入力暗号テキストが正しくないと、このプログラムは間違いなく間違いになるため、絶対に安全な暗号テキストのみを復号化してください): "<<" \ r \ n ";
  
  s = DCode(s);
  
  cout << s << "\ r \ n" << "完了" << endl;
  
  cin >> s;
  
  0を返します。
  
  }

おすすめ

転載: www.cnblogs.com/zhenhua1618/p/12729709.html