OpenSSL APIに基づく楕円曲線メネゼス-ヴァンストーン暗号システムの実装

こんにちは、カブロビテス! 控えめなニーズのために暗号化を行って、適切なレベルのデータセキュリティを維持しようとしているため( ここで ecryptセクションにリストされているレベルに焦点を当てています)、RSA暗号化アルゴリズムを使用するときにパフォーマンスの低下を心配し始めました。



残念ながら、このアルゴリズムは、非対称暗号アルゴリズムを使用して小さなデータブロックの暗号化/復号化を可能にするopensslの唯一のアルゴリズムであることが判明しました(記事の意味-対称暗号化アルゴリズムのキー)。



インターネットを歩いてみると、次のことがわかりました。



1. El-Gamalは正常に暗号化/復号化できますが、これらの操作はopensslには実装されていません(libgcryptには実装があります)。 速度に関しては、El-GamalはRSAの3倍高速です。

キーの長さが同じで、キーの1ビットあたりの暗号強度が同じです。



2. Elliptic Curve cryptosystem(ECC)は、1ビットキーの速度と暗号強度に喜んで驚いていましたが、ECCに基づく暗号化/復号化操作はopensslに実装されていません。

libgcryptでのECC暗号化の実装は、非常に具体的です。 要するに、暗号化されたメッセージmは楕円曲線mGの点にマッピングされ、ECCをハッキングするか、mのすべての可能な値を列挙しない限り、そこから元のメッセージmを取得することはできません。



3.文献[1]はMenezes-Vanstone ECCについて説明していますが、その「脆弱性」の通知があります[2]

この質問をさらに詳しく調べてみましょう。



ちょっとした数学:



簡単にするために、楕円曲線についてのみ説明します。楕円曲線の形式は、ワイエルシュトラス方程式で記述されます y2=x3+ax+b Zpとして定義された整数のフィールド上で、Zpは、ある素数pより小さく、ゼロより大きい整数のセットです。



E(p、a、b)-a、bはZpに属します-は素数pと数a、bで定義される体Zp上の楕円曲線です。 次に、抽象ゼロ要素Oを決定する必要があります(ワイエルシュトラス方程式bの係数が0に等しくない場合、条件点Oについては、この点が方程式の解でなくてもx = 0、y = 0の座標を取得できます)および曲線の要素(点)を追加する操作これにより、同じ曲線に属する新しいポイントが得られます。



当然、P + Q = Q + P、(P + Q)+ R = P +(Q + R)、P + O = O + P = Pであり、P(x、y)がある場合、つまり-P =(x、-y)およびP +(-P)= PP = O



これらはすべて、楕円曲線の点のグループに対して定義される数学的操作です。

文献[1]では、これらの操作がどのように決定されるかの数学的な詳細を見つけることができます。



異なるポイント(P = G + Q)を追加するか、ポイントを追加できます(P = Q + Q)。 「乗算」について説明するのは、レコードを短くする方法であり、P = Q + Q + Q + Q + ... + Q m回ではなく、P = mQと書くだけです。 実際、「乗算」や「除算」という操作はなく、「累乗」や「対数を取る」という操作はありません。



この用語はよく使用されますが、楕円曲線の場合、これが通常理解することを意味するものではありません。 楕円曲線上の点をそれ自体でm回加算することは、「mによる乗算」または「mの累乗」とも呼ばれます。 これの本質は変わらず、「除算」または「対数を取る」逆操作がないため、点m * Gからmを取得することは不可能であり、Gを知っていても、「楕円曲線上の離散対数の問題」と言います。 これが確立された用語です。



この曲線では、ポイントのグループのジェネレーターである(任意の)ポイントG(Gx、Gy)が選択されます。つまり、異なるmを設定することにより、乗算の結果mGが得られ、これがポイントの循環グループを形成します(有限体Zpにいるため)。 この循環グループのサイズは、生成元Gの点の順序と呼ばれます。



したがって、楕円グループは、曲線E(p、a、b)のパラメーター、生成元Gの点(Gx、Gy)、およびord * G = Oのグループordの順序によって完全に記述されます。 これはすべて楕円曲線パラメーターと呼ばれ、通常よく知られており、secp192k1やprime256v1などの名前で識別されます。



ユーザーの秘密鍵は(秘密、ランダム)番号1 <d <ord-1

ユーザーの公開キーはポイントQです。これは秘密キーdとグループGのジェネレーターの積です。Q= dG。



楕円曲線Menezes-Vanstone暗号システム[1](MVC)は何を提供しますか?





送信者側:



1.暗号化されたメッセージmは2つの部分x1とx2に分割され、それぞれがフィールドZpの要素である必要があります。このため、それらの長さをチェックし、曲線pのパラメーターの長さと比較すれば十分です。

2.送信者は、数字1 <ks <ord-1を(秘密、ランダム)選択します。

3.送信者は、ジェネレータポイントGに数値ksを乗算します。y0= ks * G

4.送信者は、ポイントZ(Zx、Zy)を計算し、受信者Qの公開鍵に数値ksを乗算します。Z= ks * Q

5.送信者はy1 = x1 * Zx(mod p)、y2 = x2 * Zy(mod p)を計算します



送信者のコストの計算:必要な長さの乱数の生成、ポイントに数値を乗算する2つの演算、pを法とする乗算の​​2つの演算。



暗号文は、ポイントy0、番号y1、番号y2です。 ポイントには2つの数値(x、y座標)が含まれます。 暗号文の合計量は約4 * pです;長さが192ビット(24バイト)のECCキーの場合、約24 * 4 = 96バイトです。



受取人:



1.受信者は、ポイントy0がパラメーターE(p、a、b)、G、またはordで指定された曲線に属していることを確認します。

2.受信者はポイントZを計算し、暗号テキストy0に自分の秘密鍵dを掛けます。Z= d * y0 = d * ks * G = ks * d * G = ks * Q

3.受信者は、成分Z(Zx、Zy)の乗法反転を計算します。e1= inv(Zx)(mod p)、e2 = inv(Zy)(mod p)。

4.受信者はx1、x2を回復します。x1= y1 * e1(mod p)、x2 = y2 * e2(mod p)。



受信者の計算コスト:ポイントのチェックは曲線に属し、ポイントに数値を乗算する1つの操作、pを法とする乗法反転を計算する2つの操作、

pを法とする乗算の​​2つの演算。



MVCの脆弱性または脆弱性



1997年、Klaus Kiefer [2]は、MVCはその設計に反して、確率的暗号化を使用するシステムではないことを示しました。 暗号文を知って、曲線のパラメータを知って、「既知の平文攻撃」(平文を推測する攻撃)を実行することができます。



それはどのように見えますか:



曲線E(p、a、b)、G、またはordのパラメーターは既知です。 暗号文y0、y1、y2は既知です。 平文はx1、x2と仮定します。



点F(f1、f2)f1 = y1 *(inv(x1))(mod p)、f2 = y2 *(inv(x2))(mod p)が曲線E(p、a、b)に属している場合、エラー確率1 / p x1、x2は実際に必要なプレーンテキストです。



これは実際にはどういう意味ですか?



すべての値x1、x2を計算コストで整理することができます.p 2を法とする乗法の逆算を計算する2つの操作、各バリアントx1、x2を法pに乗算する2つの操作、および暗号化されたテキストに対応するプレーンテキストを見つけるためのエラー1 / pの確率。 否定的なテスト結果は常に真であり、肯定的なテスト結果は1 / pの確率で誤認識を含む場合があります。 検索操作x1、x2は十分に並列化されており、多くのプロセスは重複しない範囲の値x1、x2を個別に反復処理できます。



参照用:192または256ビットのすべての可能なキー値の列挙(計算なしの列挙のみ)を参照したいと思います。 はい、128-168ビットですら。



無効化できるのは、最大48〜64ビットの暗号化されたデータの断片のみであることが明らかです。 また、この列挙はMVCなしで配置できます。すべての可能な値を列挙してキーを見つけるタスクでは、MVCを使用する必要はありません。これは不要なエンティティです。



最後に何がありますか?



十分な大きさ(128ビット以上)のテキストを暗号化して、妥当な時間と妥当なコスト内でブルートフォースによってそれらを見つける可能性を排除する場合、この「脆弱性」は何の役割も果たしません。



現在までの最小推奨ECCキー長は192ビット(24バイト)です。 この場合の暗号化されたMVCデータの長さは2 * 24 = 48バイトを超えてはならず、最も強力なAESまたはGOSTキーの長さは256ビット(32バイト)です。



しかし、暗号化と十分な速さを得る(私の推定によれば、ECC-224はRSA-2048の5倍、ElGamal-2048の3倍)非対称暗号化アルゴリズムです。

楕円曲線メネゼス-ヴァンストーン暗号システムは、まったく不当に忘れられていると思います。

このギャップを埋めようとして、openssl APIを使用してCソースを広めました。



参照:

1.コンピュータセキュリティと暗号、ALAN G. KONHEIM、John Wiley&Sons、Inc.、ホーボーケン、ニュージャージー、2007年。ISBN-13:978-0-471-94783-7 ISBN-10:0-471- 94783-0

2. 「メネゼス-ヴァンストーン暗号システムの弱点」 、Klaus Kiefer、教授の研究グループのメンバー。 J.ブーフマン1997



// // DESCRIPTION 'EC Menezes-Vanstone cryptosystem functions openssl/Linux' // COMPILER 'gcc (GCC) 4.8.2' // FILE 'ecmv.h' // AUTHOR "Nick Korepanov" // Linux-3.10.104, glibc-2.17, OpenSSL 1.0.1u // ECC-192/224/256 // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // Author of this program can be contacted by electronic mail // korepanovnd@gmail.com // Copyright (c) 2017 Nick Korepanov. All rights reserved. // This product includes software developed by the OpenSSL Project // for use in the OpenSSL Toolkit. (http://www.openssl.org/) // COMPUTER SECURITY AND CRYPTOGRAPHY, ALAN G. KONHEIM // Published by John Wiley & Sons, Inc., Hoboken, New Jersey, 2007 // Library of Congress Cataloging-in-Publication Data: // Konheim, Alan G., 1934– // Computer security & cryptography / by Alan G. Konheim. // p. cm. // Includes bibliographical references and index. // ISBN-13: 978-0-471-94783-7 // ISBN-10: 0-471-94783-0 // 1. Computer security. 2. Cryptography. I. Title. // QA76.9.A25K638 2007 // 005.8--dc22 2006049338 // 15.9 THE MENEZES–VANSTONE ELLIPTIC CURVE CRYPTOSYSTEM, p. 443 // Another very significant source - "A Weakness of Menezes-Vanstone Cryptosystem", Klaus Kiefer, member of research group of prof. J. Buchmann, 1997 // Shortly, this work show ability of "known plain text attack (KPTA)", with probability O(1/p) of false detection. // What does it mean? If we encrypt 128-bit session key, for success KPTA we must search in 2^128 combinations of session key ... // Known plaintext attack for EC MV cryptosystem // Curve E(p,a,b) known from public key, // y0, y1, y2 - ciphertext // random select 1 < x1 < p and 1< x2 < p // calculate inversion a=inv(x1)(mod p), b=inv(x2)(mod p) // c1=a*y1(mod p), c2=b*y2(mod p) // if C(c1,c2) is point of curve E, x1 and x2 is plaintext with error probability O(1/p) // z=((c1)^3 + a*c1 + b)(mod p) // if (z^((p-1)/2))(mod p) == 1 there are 2 points (c1,+-c2) in curve E(p,a,b) //#include <stdio.h> #include <stdlib.h> #include <string.h> //#include <unistd.h> #include <openssl/rand.h> #define OPENSSL_NO_EC2M #include <openssl/ec.h> #define FORMATBIN 1 #define FORMATHEX 0 struct BinFmt192 // binary format of ECMV encrypted block, EC key = 192 bits { unsigned char y0[1+192/4]; // 2*24 byte BIGNUM + 1 header byte unsigned char z1; unsigned char y1[192/8]; // 24 bytes BIGNUM unsigned char z2; unsigned char y2[192/8]; // 24 bytes BIGNUM unsigned char z3; }; // size = 100 bytes struct BinFmt224 // binary format of ECMV encrypted block, EC key = 224 bits { unsigned char y0[1+224/4]; // 2*28 byte BIGNUM + 1 header byte unsigned char z1; unsigned char y1[224/8]; // 28 bytes BIGNUM unsigned char z2; unsigned char y2[224/8]; // 28 bytes BIGNUM unsigned char z3; }; // size = 116 bytes struct BinFmt256 // binary format of ECMV encrypted block, EC key = 256 bits { unsigned char y0[1+256/4]; // 2*32 byte BIGNUM + 1 header byte unsigned char z1; unsigned char y1[256/8]; // 32 bytes BIGNUM unsigned char z2; unsigned char y2[256/8]; // 32 bytes BIGNUM unsigned char z3; }; // size = 132 bytes // Encrypt plaintext of length len with public EC key pubkey // and store ciphertext in chipher = y0 (point), y1 (bignum), y2 (bignum) // return error code, 0 if all OK // Error codes: /* * 1 // no curve in key? * 2 // wrong plaintext has odd length * 3 // plaintext too long for this key * 8 // binary format of encrypted block not defined for this key length * 4 // internal error: ks is wrong, error in do-while * 5 // internal error: error in EC_POINT_mul y0=ks*g * 6 // internal error: error in EC_POINT_mul z=ks*q * 7 // internal error: error EC_POINT_get_affine_coordinates_GFp * errors 4,5,6,7 lead to memory leak :( * */ // hex format: // Encrypted text consist of 3 hex strings, each is ending with '\n'=0x0A // First string has '04' header and two times longer than second and third // length of encrypted block = 2*4*bits/8 + 5 = bits + 5 bytes, where 'bits' is length of EC key in bits // Plaintext data MUST be of even length in bytes and not longer than 2*bits/8 = bits/4 bytes // bin format: // Encrypted text is binary block consist of 3 binary elements, each is ending with NULL=0x00 byte // First element has 0x04 header and two times longer than second and third // length of encrypted block in binary form = 4*bits/8 + 4 = bits/2 + 4 bytes, where 'bits' is length of EC key in bits // In this example I used 192,224,256 bit EC keys and binary form for other key length don't supported :( int EC_MV_pubkey_encrypt(unsigned char *cipher, EC_KEY* pubkey, unsigned char* plaintext, size_t len, int format); // Decrypt with private EC key privkey ciphertext in cipher = y0 (point), y1 (bignum), y2 (bignum) // and store result in plaintext // return error code, 0 if all OK /* Error codes: * 1 // no curve in key? * 8 // unknown format of ECMV encrypted block * 9 // binary format of encrypted block not defined for this key length * 10 // wrong format of binary encrypted block * 2 // invalid hex point y0 representation * 3,4 // wrong format of HEX encrypted data * 11 // point y0 is not on curve * 6 // internal error: error in EC_POINT_mul z=ks*q * 7 // internal error: error EC_POINT_get_affine_coordinates_GFp * errors 2,3,4,11,6,7 lead to memory leak :( * */ int EC_MV_privkey_decrypt(unsigned char* cipher, EC_KEY *privkey, unsigned char* plaintext);
      
      







 // // DESCRIPTION 'EC Menezes-Vanstone cryptosystem functions openssl/Linux' // COMPILER 'gcc (GCC) 4.8.2' // FILE 'ecmv.c' // AUTHOR "Nick Korepanov" // Linux-3.10.104, glibc-2.17, OpenSSL 1.0.1u // ECC-192/224/256 // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // Author of this program can be contacted by electronic mail // korepanovnd@gmail.com // Copyright (c) 2017 Nick Korepanov. All rights reserved. // This product includes software developed by the OpenSSL Project // for use in the OpenSSL Toolkit. (http://www.openssl.org/) #include "ecmv.h" int EC_MV_pubkey_encrypt(unsigned char *cipher, EC_KEY* pubkey, unsigned char* plaintext, size_t len, int format) { const EC_GROUP *curve; // curve, q and g are part of pubkey, it was allocated and free with pubkey const EC_POINT *q; EC_POINT *y0, *z; BIGNUM *p, *a, *b, *ks, *o1, *z1, *z2, *y1, *y2, *x1, *x2, *ord; int bits, i=0, err; unsigned char buffer[250]; //size_t length; BN_CTX *ctx; curve=EC_KEY_get0_group(pubkey); if(curve) bits = EC_GROUP_get_degree(curve); else return 1; // no curve in key? if(len%2) return 2; // wrong plaintext has odd length if(len > 2*bits/8) return 3; // plaintext too long for this key if( !(bits == 192 || bits == 224 || bits == 256) && format) return 8; // binary format of encrypted block not defined for this key length //prepare bignums p=BN_new(); a=BN_new(); b=BN_new(); ks=BN_new(); o1=BN_new(); z1=BN_new(); z2=BN_new(); y1=BN_new(); y2=BN_new(); x1=BN_new(); x2=BN_new(); ord=BN_new(); ctx=BN_CTX_new(); //prepare points //q=EC_POINT_new(curve); g=EC_POINT_new(curve); y0=EC_POINT_new(curve); z=EC_POINT_new(curve); // split plaintext at two parts, and assign it to BIGNUMs BN_bin2bn(plaintext, len/2, x1); BN_bin2bn(plaintext+len/2, len/2, x2); // get public key q q=EC_KEY_get0_public_key(pubkey); // get generator point g //g=EC_GROUP_get0_generator(curve); // get order of g EC_GROUP_get_order(curve, ord, ctx ); // get prime p EC_GROUP_get_curve_GFp(curve, p, a, b, ctx ); BN_sub(o1, ord, BN_value_one()); // o1=ord-1 do { if( i>= 10) break; // make secret session key ks > 1 and ks < (o-1) RAND_bytes(buffer, bits/8); BN_bin2bn(buffer, bits/8, ks); i++; } while( BN_cmp(BN_value_one(), ks) >=0 || BN_cmp(o1,ks) <=0 ); if(i>=10) return 4; // ks is wrong, error in do-while // y0=ks*g err=EC_POINT_mul(curve, y0, ks, NULL, NULL, ctx ); if(err == 0) return 5; // error in EC_POINT_mul y0=ks*g // z=ks*q err=EC_POINT_mul(curve, z, NULL, q, ks, ctx ); if(err == 0) return 6; // error in EC_POINT_mul z=ks*q // get z1,z2 = Z(z1,z2) err=EC_POINT_get_affine_coordinates_GFp(curve, z, z1, z2, ctx ); if(err == 0) return 7; //error EC_POINT_get_affine_coordinates_GFp //y1 = z1*x1(modulo p) //y2 = z2*x2(modulo p) BN_mod_mul(y1, z1, x1, p, ctx); BN_mod_mul(y2, z2, x2, p, ctx); /* if bits=192, 24 bytes per every BIGNUM, point contains 2 Bignum + 1 byte header */ if(format) { // bin format if(bits == 192) { struct BinFmt192 *out; out=(struct BinFmt192 *)cipher; EC_POINT_point2oct(curve, y0, POINT_CONVERSION_UNCOMPRESSED, (unsigned char*)&out->y0, sizeof(out->y0), ctx); BN_bn2bin(y1, (unsigned char*)&out->y1); BN_bn2bin(y2, (unsigned char*)&out->y2); out->z1=out->z2=out->z3=0; } if(bits == 224) { struct BinFmt224 *out; out=(struct BinFmt224 *)cipher; EC_POINT_point2oct(curve, y0, POINT_CONVERSION_UNCOMPRESSED, (unsigned char*)&out->y0, sizeof(out->y0), ctx); BN_bn2bin(y1, (unsigned char*)&out->y1); BN_bn2bin(y2, (unsigned char*)&out->y2); out->z1=out->z2=out->z3=0; } if(bits == 256) { struct BinFmt256 *out; out=(struct BinFmt256 *)cipher; EC_POINT_point2oct(curve, y0, POINT_CONVERSION_UNCOMPRESSED, (unsigned char*)&out->y0, sizeof(out->y0), ctx); BN_bn2bin(y1, (unsigned char*)&out->y1); BN_bn2bin(y2, (unsigned char*)&out->y2); out->z1=out->z2=out->z3=0; } } else { // hex format strcpy((char*)cipher, EC_POINT_point2hex(curve, y0, POINT_CONVERSION_UNCOMPRESSED, ctx)); strcat((char*)cipher, "\n"); strcat((char*)cipher, BN_bn2hex(y1)); strcat((char*)cipher, "\n"); strcat((char*)cipher, BN_bn2hex(y2)); strcat((char*)cipher, "\n"); } // free points //EC_POINT_free(q); EC_POINT_free(g); EC_POINT_free(y0); EC_POINT_clear_free(z); BN_CTX_free(ctx); BN_clear(ks); BN_clear(x1); BN_clear(x2); BN_clear(z1); BN_clear(z2); //free bignums BN_free(p); BN_free(a); BN_free(b); BN_free(ks); BN_free(o1); BN_free(z1); BN_free(z2); BN_free(y1); BN_free(y2); BN_free(x1); BN_free(x2); BN_free(ord); return 0; } int EC_MV_privkey_decrypt(unsigned char* cipher, EC_KEY *privkey, unsigned char* plaintext) { const EC_GROUP *curve; // curve, d are part of privkey, it was allocated and free with privkey const BIGNUM *d; EC_POINT *y0, *z; BIGNUM *p, *a, *b, *z1, *z2, *y1, *y2, *x1, *x2; int err, bits, format; unsigned char *ptr; BN_CTX *ctx; ctx=BN_CTX_new(); curve=EC_KEY_get0_group(privkey); if(!curve) return 1; // no curve in key? bits = EC_GROUP_get_degree(curve); if( cipher[0] == 0x04 ) format=FORMATBIN; if( cipher[0] == 0x30 ) format=FORMATHEX; if(cipher[0] != 0x04 && cipher[0] != 0x30) return 8; // unknown format of ECMV encrypted block if( !(bits == 192 || bits == 224 || bits == 256) && format) return 9; // binary format of encrypted block not defined for this key length if(format && bits == 192 && (cipher[48+1] || cipher[48+1+24+1] || cipher[48+1+24+1+24+1] )) return 10; //wrong format of binary encrypted block if(format && bits == 224 && (cipher[56+1] || cipher[56+1+28+1] || cipher[56+1+28+1+28+1] )) return 10; //wrong format of binary encrypted block if(format && bits == 256 && (cipher[64+1] || cipher[64+1+32+1] || cipher[64+1+32+1+32+1] )) return 10; //wrong format of binary encrypted block //prepare bignums p=BN_new(); a=BN_new(); b=BN_new(); z1=BN_new(); z2=BN_new(); y1=BN_new(); y2=BN_new(); x1=BN_new(); x2=BN_new(); //prepare points y0=EC_POINT_new(curve); z=EC_POINT_new(curve); // get private key d d=EC_KEY_get0_private_key(privkey); // get prime p EC_GROUP_get_curve_GFp(curve, p, a, b, ctx); if(format) { if(bits == 192) { struct BinFmt192 *in; in=(struct BinFmt192 *)cipher; EC_POINT_oct2point(curve, y0, (const unsigned char *)&in->y0, sizeof(in->y0), ctx); BN_bin2bn((const unsigned char *)&in->y1, sizeof(in->y1), y1); BN_bin2bn((const unsigned char *)&in->y2, sizeof(in->y2), y2); } if(bits == 224) { struct BinFmt224 *in; in=(struct BinFmt224 *)cipher; EC_POINT_oct2point(curve, y0, (const unsigned char *)&in->y0, sizeof(in->y0), ctx); BN_bin2bn((const unsigned char *)&in->y1, sizeof(in->y1), y1); BN_bin2bn((const unsigned char *)&in->y2, sizeof(in->y2), y2); } if(bits == 256) { struct BinFmt256 *in; in=(struct BinFmt256 *)cipher; EC_POINT_oct2point(curve, y0, (const unsigned char *)&in->y0, sizeof(in->y0), ctx); BN_bin2bn((const unsigned char *)&in->y1, sizeof(in->y1), y1); BN_bin2bn((const unsigned char *)&in->y2, sizeof(in->y2), y2); } } else { // read y0 ptr=cipher; y0=EC_POINT_hex2point(curve, (const char *)ptr, y0, ctx); if(y0 == NULL) return 2; //invalid hex point representation //read y1,y2 ptr=strchr((const char *)ptr,'\n'); if(ptr == NULL) return 3; //wrong format of encrypted data ptr++; BN_hex2bn(&y1, (const char *)ptr); ptr=strchr((const char *)ptr,'\n'); if(ptr == NULL) return 4; //wrong format of encrypted data ptr++; BN_hex2bn(&y2, (const char *)ptr); } if( !EC_POINT_is_on_curve(curve, (const EC_POINT *)y0, ctx) ) return 11; // point is not on curve // z=d*y0=d*ks*g=ks*q err=EC_POINT_mul(curve, z, NULL, y0, d, ctx ); if(err == 0) return 6; // error in EC_POINT_mul z=ks*q // get z1,z2 = Z(z1,z2) err=EC_POINT_get_affine_coordinates_GFp(curve, z, z1, z2, ctx ); if(err == 0) return 7; //error EC_POINT_get_affine_coordinates_GFp // a=inv(z1)(mod p) BN_mod_inverse(a, z1, p, ctx); // b=inv(z2)(mod p) BN_mod_inverse(b, z2, p, ctx); //x1 = a*y1(modulo p) //x2 = b*y2(modulo p) BN_mod_mul(x1, a, y1, p, ctx); BN_mod_mul(x2, b, y2, p, ctx); // decode plaintext from two parts BN_bn2bin(x1, plaintext); BN_bn2bin(x2, plaintext+BN_num_bytes(x1)); // free points EC_POINT_free(y0); EC_POINT_clear_free(z); BN_CTX_free(ctx); BN_clear(x1); BN_clear(x2); BN_clear(z1); BN_clear(z2); BN_clear(a); BN_clear(b); //free bignums BN_free(p); BN_free(a); BN_free(b); BN_free(z1); BN_free(z2); BN_free(y1); BN_free(y2); BN_free(x1); BN_free(x2); return 0; }
      
      





ご清聴ありがとうございました!



All Articles