RSA暗号について
RSA暗号について
前回(AESの質問)と同じく、RSA暗号について分からない点があり、調べてもあいまいなことしか書いてなかったりそもそも載っていなかったりと不明な点がありますので、こちらで質問させていただきます。
C言語でOpenSSLのRSA暗号を使い通信するソフトを作っています。
前回AES暗号が出来上がりましたので、それをRSAを使って相手に送信したいのです。
質問内容をまとめました。
・作成した公開鍵と秘密鍵をPEMファイルに出力してそのデータ(公開鍵)を相手に送信するのか。
・秘密鍵をPEMファイルとして出力した際、セキュリティ的に安全か。
・そもそも鍵をPEMとして出力する必要があるのか。
・もし出力しなくてよい場合、どのデータ(鍵)を相手に渡すのか。
サンプルなどを見て作っていたのですが、多種多様な物ばかりでRSAについて理解できずにいます。
どうかよろしくお願いします。
C言語でOpenSSLのRSA暗号を使い通信するソフトを作っています。
前回AES暗号が出来上がりましたので、それをRSAを使って相手に送信したいのです。
質問内容をまとめました。
・作成した公開鍵と秘密鍵をPEMファイルに出力してそのデータ(公開鍵)を相手に送信するのか。
・秘密鍵をPEMファイルとして出力した際、セキュリティ的に安全か。
・そもそも鍵をPEMとして出力する必要があるのか。
・もし出力しなくてよい場合、どのデータ(鍵)を相手に渡すのか。
サンプルなどを見て作っていたのですが、多種多様な物ばかりでRSAについて理解できずにいます。
どうかよろしくお願いします。
Dango San
Re: RSA暗号について
目的によります。だんごさん さんが書きました: ・作成した公開鍵と秘密鍵をPEMファイルに出力してそのデータ(公開鍵)を相手に送信するのか。
PEMは単なるフォーマットなので安全かどうかは分かりません。だんごさん さんが書きました: ・秘密鍵をPEMファイルとして出力した際、セキュリティ的に安全か。
パスフレーズ付きのPEMファイルを作成することも可能です。
目的によります。アプリケーションがPEMにしか対応していないならPEMで出力する必要があるでしょう。だんごさん さんが書きました: ・そもそも鍵をPEMとして出力する必要があるのか。
OpenSSLの鍵の構造体はこのようになっていますがだんごさん さんが書きました: ・もし出力しなくてよい場合、どのデータ(鍵)を相手に渡すのか。
nとeが公開鍵にあたります。struct
{
BIGNUM *n; // public modulus
BIGNUM *e; // public exponent
BIGNUM *d; // private exponent
BIGNUM *p; // secret prime factor
BIGNUM *q; // secret prime factor
BIGNUM *dmp1; // d mod (p-1)
BIGNUM *dmq1; // d mod (q-1)
BIGNUM *iqmp; // q^-1 mod p
// ...
};
Re: RSA暗号について
h2so5 さんが書きました:目的によります。
すみません。目的は上記ではだめですか?目的とはどういったことでしょうか?だんごさん さんが書きました:前回AES暗号が出来上がりましたので、それをRSAを使って相手に送信したいのです。
Dango San
Re: RSA暗号について
AESとRSAを組み合わせる、ということしか分からないのでなんとも言えません。
RSAは単なるアルゴリズムですので、どのように暗号を運用するかは別の話です。
RSAは単なるアルゴリズムですので、どのように暗号を運用するかは別の話です。
Re: RSA暗号について
AESの共通鍵をRSAを使い暗号化して送信するために、まずRSAの公開鍵を相手に渡す作業を行いたいです。h2so5 さんが書きました:AESとRSAを組み合わせる、ということしか分からないのでなんとも言えません。
説明が下手で申し訳ないです…。
もしPEMファイルに出力せずにRSA構造体のnとeを相手に送ったとして、暗号化関数に渡すRSA構造体の作成はどう行うのでしょうか?
仮にPEMだと、PEM_read_RSAPublicKeyでRSA構造体が返されますが、nとeを送った場合RSA構造体にnとeを直接入れてもいいのでしょうか?
Dango San
Re: RSA暗号について
おそらく直接入れても大丈夫だと思います。だんごさん さんが書きました: もしPEMファイルに出力せずにRSA構造体のnとeを相手に送ったとして、暗号化関数に渡すRSA構造体の作成はどう行うのでしょうか?
仮にPEMだと、PEM_read_RSAPublicKeyでRSA構造体が返されますが、nとeを送った場合RSA構造体にnとeを直接入れてもいいのでしょうか?
Re: RSA暗号について
すみません、自分で「nとeを直接入れてもいいか」と聞きましたがやり方が分かりませんでした…。h2so5 さんが書きました:おそらく直接入れても大丈夫だと思います。だんごさん さんが書きました: もしPEMファイルに出力せずにRSA構造体のnとeを相手に送ったとして、暗号化関数に渡すRSA構造体の作成はどう行うのでしょうか?
仮にPEMだと、PEM_read_RSAPublicKeyでRSA構造体が返されますが、nとeを送った場合RSA構造体にnとeを直接入れてもいいのでしょうか?
nとeを代入する前にRSA構造体は初期化しなければならないと思うのですが、そういった関数はあるのでしょうか?
またnとeはbignum_st構造体からなっているのですが、単純にBN_bn2hexで文字列化して送信し、また戻して代入する形で良いでしょうか?
Dango San
Re: RSA暗号について
検証した結果、大丈夫でした。h2so5 さんが書きました:おそらく直接入れても大丈夫だと思います。だんご さんが書きました: もしPEMファイルに出力せずにRSA構造体のnとeを相手に送ったとして、暗号化関数に渡すRSA構造体の作成はどう行うのでしょうか?
仮にPEMだと、PEM_read_RSAPublicKeyでRSA構造体が返されますが、nとeを送った場合RSA構造体にnとeを直接入れてもいいのでしょうか?
"// 3.2. get public key from the clone" で n と e のみコピーしたRSA構造体からpublickey抽出をやっています。
[環境]CentOS 6.5, gcc 4.9.0, binutils 2.24, openssl 1.0.1e-16.el6_5.15
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
using namespace std;
void print(BIO* pbio)
{
string key;
char buff[512];
int readbytes;
while((readbytes = BIO_gets(pbio, buff, sizeof(buff))) > 0) {
key.append(buff, readbytes);
}
cout << key << endl;
}
bool generate_rsa_key()
{
int ret = 0;
BIGNUM* bignum;
RSA* rsa;
BIO* pbio_private;
BIO* pbio_public;
RSA* clone;
BIO* pbio_clone;
// 1. generate rsa key
//-------------------------------------------------
bignum = BN_new();
ret = BN_set_word(bignum, RSA_F4);
if(ret != 1) goto finally;
rsa = RSA_new();
ret = RSA_generate_key_ex(rsa, 2048, bignum, NULL);
if(ret != 1) goto finally;
//-------------------------------------------------
// 2. get private key
//-------------------------------------------------
//BIO* pbio_private = BIO_new_file("private.pem", "w+"); //output to file
pbio_private = BIO_new(BIO_s_mem()); //output to memory
ret = PEM_write_bio_RSAPrivateKey(pbio_private, rsa, NULL, NULL, 0, NULL, NULL);
if(ret != 1) goto finally;
//-------------------------------------------------
print(pbio_private);
// 3.1. get public key
//-------------------------------------------------
//BIO* pbio_public = BIO_new_file("public.pem", "w+"); //output to file
pbio_public = BIO_new(BIO_s_mem()); //output to memory
ret = PEM_write_bio_RSAPublicKey(pbio_public, rsa);
if(ret != 1) goto finally;
//-------------------------------------------------
print(pbio_public);
// 3.2. get public key from the clone
//-------------------------------------------------
clone = RSA_new();
// n copy
clone->n = (BIGNUM*)malloc(sizeof(BIGNUM));
memcpy(clone->n, rsa->n, sizeof(BIGNUM));
clone->n->d = (BN_ULONG*)malloc(sizeof(BN_ULONG) * rsa->n->dmax);
memcpy(clone->n->d, rsa->n->d, sizeof(BN_ULONG) * rsa->n->dmax);
// e copy
clone->e = (BIGNUM*)malloc(sizeof(BIGNUM));
memcpy(clone->e, rsa->e, sizeof(BIGNUM));
clone->e->d = (BN_ULONG*)malloc(sizeof(BN_ULONG) * rsa->e->dmax);
memcpy(clone->e->d, rsa->e->d, sizeof(BN_ULONG) * rsa->e->dmax);
pbio_clone = BIO_new(BIO_s_mem()); //output to memory
ret = PEM_write_bio_RSAPublicKey(pbio_clone, clone);
if(ret != 1) goto finally;
//-------------------------------------------------
print(pbio_clone);
// 4. finally
//-------------------------------------------------
finally:
BIO_free_all(pbio_clone);
BIO_free_all(pbio_public);
BIO_free_all(pbio_private);
RSA_free(clone);
RSA_free(rsa);
BN_free(bignum);
return (ret == 1);
//-------------------------------------------------
}
int main()
{
generate_rsa_key();
return 0;
}
Re: RSA暗号について
途中でfinallyにジャンプすると初期化していないポインタに対してfreeを実行することになるので危険です。
Re: RSA暗号について
はい、ご指摘ありがとうございます。
掲示の際、文字を読みやすくするために削除させていただきました。
必要とされている方に、必要な情報は伝えれたと思っています。
掲示の際、文字を読みやすくするために削除させていただきました。
必要とされている方に、必要な情報は伝えれたと思っています。
Re: RSA暗号について
通信の方で詰まっていて遅れてしまいました。
検証ソースありがとうございます!だいぶ出来上がりました。
ですが、現在復号の時にエラーが出てしまいます。
相手から自分の渡した公開鍵で暗号して送ってもらい、こちら側で復号しようとしたところ、
error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
とエラーが出ます。
色々とデバッグしてみたのですが見当たるものはなく、そもそもこのエラーが何を示しているのかが分かりません。
どういった時に出るのか、ヒントをくれませんでしょうか?
検証ソースありがとうございます!だいぶ出来上がりました。
ですが、現在復号の時にエラーが出てしまいます。
相手から自分の渡した公開鍵で暗号して送ってもらい、こちら側で復号しようとしたところ、
error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
とエラーが出ます。
色々とデバッグしてみたのですが見当たるものはなく、そもそもこのエラーが何を示しているのかが分かりません。
どういった時に出るのか、ヒントをくれませんでしょうか?
Dango San
Re: RSA暗号について
普通は、暗号化した公開鍵に対応する秘密鍵以外で復号しようとすると出ます。だんごさん さんが書きました:通信の方で詰まっていて遅れてしまいました。
検証ソースありがとうございます!だいぶ出来上がりました。
ですが、現在復号の時にエラーが出てしまいます。
相手から自分の渡した公開鍵で暗号して送ってもらい、こちら側で復号しようとしたところ、
error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
とエラーが出ます。
色々とデバッグしてみたのですが見当たるものはなく、そもそもこのエラーが何を示しているのかが分かりません。
どういった時に出るのか、ヒントをくれませんでしょうか?
Re: RSA暗号について
詳しく調べてみました。
実は送信時にBIGNUMの値をBN_bn2hexで文字列化しています。送りやすいのと管理のしやすさのためです。
文字列化前はnの中身が
top:64
dmax:128
neg:0
となっているのですが、BN_hex2bnでBIGNUMに戻すと
top:64
dmax:64
neg:0
となってしまいます。
これは復号の時に影響が出るものでしょうか?
実は送信時にBIGNUMの値をBN_bn2hexで文字列化しています。送りやすいのと管理のしやすさのためです。
文字列化前はnの中身が
top:64
dmax:128
neg:0
となっているのですが、BN_hex2bnでBIGNUMに戻すと
top:64
dmax:64
neg:0
となってしまいます。
これは復号の時に影響が出るものでしょうか?
Dango San
Re: RSA暗号について
復号には影響でません。だんごさん さんが書きました:詳しく調べてみました。
実は送信時にBIGNUMの値をBN_bn2hexで文字列化しています。送りやすいのと管理のしやすさのためです。
文字列化前はnの中身が
top:64
dmax:128
neg:0
となっているのですが、BN_hex2bnでBIGNUMに戻すと
top:64
dmax:64
neg:0
となってしまいます。
これは復号の時に影響が出るものでしょうか?
dmaxは、マニュアルにもあるとおり
オフトピック
dmax is the size of the d array that has been allocated.
BN_hex2bnの際、d を格納するために必要と判断されたサイズが確保されているだけです。
Re: RSA暗号について
できました…!
トピックを立てて1ヵ月になりましたが、みなさんありがとうございました!
復号できなかった主な原因として、暗号化した文に終端文字が含まれていることでした。
暗号化した文字列をコピーする際に、256バイト分あるはずが、途中で終端文字に出会い中途半端なところで切られていました。
よって全てのコピー関数をmemcpyにしてサイズ指定することで解決いたしました。
本当にありがとうございました。
トピックを立てて1ヵ月になりましたが、みなさんありがとうございました!
復号できなかった主な原因として、暗号化した文に終端文字が含まれていることでした。
暗号化した文字列をコピーする際に、256バイト分あるはずが、途中で終端文字に出会い中途半端なところで切られていました。
よって全てのコピー関数をmemcpyにしてサイズ指定することで解決いたしました。
本当にありがとうございました。
Dango San