|
>>3866 鶏 ご指摘のとおりかと思います。というわけで、修正しました。 http://X68000.q-e-d.net/~68user/unix/pickup?cp ありがとうございました。 >>3867 ニッタン > ここまで調べるのは苦労しませんでしたか? 調べるのに 3日かかってますので、苦労しました。 でも、なぜ RAND_poll() したらエラーにならないのかいまいち わかっていません (別にこれがわからなくても構わないんですが、 気になるもので)。 >>3868 jeiu > どこで実装されるものなのでしょうか? OpenSSL のライブラリの中です。 SSL/TLS はクライアントが利用可能な暗号 (正しくは暗号スイート) を 提示し、サーバがその中から選びます。よって常に RSA が使用される わけではありません (DH を使う場合もある)。 で、暗号スイートを提示したり、RSA で暗号化・復号化したり、 DH で鍵交換したり、プレマスターシークレットを送ったり、 ということはすべて OpenSSL のライブラリ中で記述されています。 |
|
>調べるのに 3日かかってますので、苦労しました。 でしたら、やはりお持ちのマスタリングTCP/IP SSL/TLS編を 辞書的に使いながら追いかける方がいいかもしれませんよ。 >でも、なぜ RAND_poll() したらエラーにならないのかいまいち わかっていません 結局、RAND_poll()内で乱数の種をプロセスIDや/dev/randomなどを使って作成して RAND_add()しているからだと思います。 RAND_seed()も結局、RAND_add()をしていますし。 |
|
>>3870 ニッタン /dev/random や /dev/urandom がない環境ではエラーになるが、 RAND_poll() を呼ぶとうまくいくと。 ということはおそらく RAND_poll() を呼ぶと http://snapshots.jp.freebsd.org/tour/current/userland/S/7348.html#145 に処理が移ると思います。 # このソースは OpenSSL 0.9.7d です。 ここでは /dev/random や /dev/urandom を読んでいろいろやって ますが、/dev/random や /dev/urandom がない環境なので、結局は unsigned long l; l=curr_pid; RAND_add(&l,sizeof(l),0); l=getuid(); RAND_add(&l,sizeof(l),0); l=time(NULL); RAND_add(&l,sizeof(l),0); だけが実行されると思います。ここで 第三引数の entropy には全て 0 を 渡しています。 RAND_add を呼ぶと ssleay_rand_add が呼ばれ、 http://snapshots.jp.freebsd.org/tour/current/userland/S/7341.html#190 が実行されます。 if (ok) return(1); else RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); とあるのがエラーになっている箇所かと思います。つまり RAND_poll() を 呼ぶと ok が真になり、RAND_poll() を呼ばないと偽になる、と。ここで ok とは何かというと ok = (entropy >= ENTROPY_NEEDED); です。ENTROPY_NEEDED は ./crypto/rand/rand_lcl.h:#define ENTROPY_NEEDED 32 /* require 256 bits = 32 bytes of randomness */ なので、entropy <= 32 なときに RPNG_NOT_SEEDED でエラーになる。 逆に言えば、RAND_poll() を呼ぶと entropy >= 32 になるためうまく いくようになる、ということです。しかし entropy を増やしているのは entropy += add; しかないような気がします。でも、add は RAND_add() の第三引数で、 今回はすべて 0 が渡されています。よって、 entropy += 0; となるわけです。それなのになぜ entropy が増えて >=32 になるのか わからないなぁ、といったところで止まっています。 「マスタリングTCP/IP SSL/TLS編」は調べましたが、内部構造には 触れていようで見つけられませんでした。もしどこかに載っていたら 教えてください。 |
|
>>3872 68user 続きです。 こちらには /dev/random・/dev/urandom が存在しない環境がないため、 FreeBSD で OpenSSL のソースをいじって、無理矢理 /dev/random・ /dev/urandom が存在しない状況を作ってみました。その結果、 PRNG not seeded なエラーが発生しました。 しかし SSL_connect() の直前に RAND_poll() を挿入しても、同じく PRNG not seeded となりました。そこで確認させていただきたいのですが、 >>3845 ニッタン > SSL_connect()するまでに以下の関数のどれかを使うと良い様です。 > 3、RAND_poll() > 一番楽なのは3を使うのが楽ですし、一般的で確実かもしれません。 はそちらの環境では正常に動作しているのですよね? |
|
回答ありがとうございます。 もうひとつ教えてください。 >SSL/TLS はクライアントが利用可能な暗号 (正しくは暗号スイート) を >提示し、サーバがその中から選びます。よって常に RSA が使用される >わけではありません (DH を使う場合もある)。 クライアントから提示する暗号方式とはなにをもとに決められるのでしょうか? たとえば、SSL V2に対応したアプリケーションとかV3に対応した アプリケーションとかで決まることなのでしょうか? または、Open SSL等で自力でSLLを実装するような場合は、対応できる暗号方式が 特定される(できる?)のであれば、それだけでは決まらないような気もしますが...。 |
|
>>3873 jeiu > クライアントから提示する暗号方式とはなにをもとに決められるのでしょうか? クライアント作成者が勝手に決めます。例えば 3DES と RC4 はいいけど DES は暗号強度が気に入らないから使わないとか、MD5 より強固な SHA-1 を 使うとか。 OpenSSL であれば SSL_CTX_set_cipher_list() を使って好きな暗号 スイートをセットすればよいでしょう。 暗号スイートは具体的には http://www21.ocn.ne.jp/~k-west/SSLandTLS/rfc2246-Ja.txt の TLS_RSA_WITH_3DES_EDE_CBC_SHA TLS_DH_anon_WITH_3DES_EDE_CBC_SHA などを指します。 上記 RFC の ClientHello がクライアントからの暗号スイートの提示、 ServerHello がサーバからの暗号スイート決定通知、です。 > または、Open SSL等で自力でSLLを実装するような場合は、対応できる暗号方式が > 特定される(できる?)のであれば、それだけでは決まらないような気もしますが...。 これは意味がわかりませんでした。 |
|
誤解を招くような書き方をしてしまいました。 申し訳ありません。 まず、RAND_poll()はRAND_byte()やRAND_status()の始めての呼び出しの際に 一度だけ呼ばれていると思われます。 RAND_poll()内では/dev/random・/dev/urandomを使用して 乱数の種を作っています。 /dev/random・/dev/urandomが存在しない環境でも 上記の様にRAND_poll()は呼ばれていますが、 No.3871の通り 乱数の種は作られません。 そこで、RAND_poll()を自前で呼び出しても同じ結果になります。 つまり、RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDEDのエラーが 発生した時は RAND_poll()で乱数の種を作成するのに失敗しているので、 自前で乱数の種を作らないといけない と言った説明を追記して頂ければいいと思います。 自前で乱数の種を作るのが 1、RAND_load_file() や 2、RAND_seed() と言う訳です。 貴重な時間を割かせてしまいまして、申し訳ありませんでした。 |
|
>>3875 ニッタン 更新しました。長らくお待たせしてすいません。 http://X68000.q-e-d.net/~68user/net/ssl-1.html 詳しく説明しようとして、ドツボにはまった感がありますが、 いかがでしょうか。 RAND_status を呼べばその中から RAND_poll が呼ばれるのですが、 あえて RAND_poll を呼んでいるのは、マニュアルに書いてないこと はなるべく前提としないでおこう、という方針だからです。 最初のサンプルプログラムがこれではわかりづらすぎるかなぁ。 |
|
ありがとうございます。 色々と勉強したので、私には理解できますが、 今後、初心者が読んだ場合に理解できるかはどうかは、 この掲示板にでも書き込んでくれる事を期待して、 この話題は一旦終了しましょう。 >最初のサンプルプログラムがこれではわかりづらすぎるかなぁ。 結局、/dev/randomがない環境では、種を作らないとエラーになるので 仕方ないと思います。 一応、/dev/randomがある環境では必要ないと補足してありますし。 今までありがとうございました。今後も参考にさせて頂きます。 |
|
>> または、Open SSL等で自力でSLLを実装するような場合は、対応できる暗号方式が >> 特定される(できる?)のであれば、それだけでは決まらないような気もしますが...。 >これは意味がわかりませんでした。 わけのわからない質問をしてすみません。 聞きたかったのは、クライアントが決める暗号化方式はどこで定義するのか? とういうことでした。 あるHPでは、「暗号化に関する特許などが絡んでいるため、わけのわからないものは コンパイルオプションを使って使用しないほうがよいでしょう」と書かれていたり、 ちょっと混乱状態です。 も少し勉強が必要かなと思います。 |
|
68user殿 No.3874の >OpenSSL であれば SSL_CTX_set_cipher_list(ctx,ciphers) を使って好きな暗号 >スイートをセットすればよいでしょう。 のciphersには具体的にはどのような設定をすればよいのでしょうか? いずれにしても、どの暗号化方式を利用するかは上記のようにプログラミング依存 ということになるんでしょうか?(とすると、No.3878にも書かせていただきましたが 「コンパイルオプションを使って...」は何を意味するのでしょう。ご存知でしたら教 えてください)。 |
|
>>3879 jeiu > ciphersには具体的にはどのような設定をすればよいのでしょうか? 概念は 3874で書いたとおり > 例えば 3DES と RC4 はいいけどDES は暗号強度が気に入らないから使わない などです。 ソースでどう書くかという意味なら SSL_CTX_set_cipher_list(ctx, "3DES:RC4"); や SSL_CTX_set_cipher_list(ctx, "ALL:-DES"); などです。書き方は OpenSSL のマニュアル ciphers(1) に載っています。 > 「コンパイルオプションを使って...」は何を意味するのでしょう。 「あるHPでは」などと曖昧なことを書かずに http://www.ryouto.jp/linux/linux_22.html とはっきり書いてください (上記の URL であってるかはわかりませんが)。 文脈を無視して一文を切り出されても、答える方は推測しなければ いけないのでつらいです。たとえば上記の web であれば config で no-rc5 no-idea と指定しているので、このページの作者は RC5 と IDEA の特許について 危惧しているのだなということがわかるわけです。クイズじゃないんです から、はっきり質問したいことを書きましょう。 IDEA については SSL/TLS 上で使えますし、普通に OpenSSL をコンパイル した場合は有効になっています。ただし FreeBSD の OpenSSL では IDEA が 使用できないようにコンパイルされていました。他の厳しめの OS (Debian とか) でも同様かと思われます。SSL/TLS で使用できるようになっているか どうかは % openssl ciphers でわかります。 RC5 は SSL/TLS で使用できる暗号スイートに入っていないので、 問題ないでしょう。 SSL/TLS ではなく、共通鍵暗号方式として IDEA や RC5 を使いたくない (openssl enc -e idea や openssl enc -e rc5 とできないようにしたい) ということであれば、上記のページのようにコンパイルオプションを 設定すればよいでしょう。使用中の OpenSSL で使えるかどうかを知りたい なら % openssl enc -h で表示される Cipher Types を見ればよいです。 なお、サーバ側で制御したいのであれば、Apache などの設定ファイルで http://httpd.apache.org/docs-2.0/mod/mod_ssl.html#sslciphersuite を設定してください。 今後質問される場合は、質問の背景と、何が知りたいのかを明確にする ことをお勧めします。 例: - SSL/TLS クライアントを作っている - 〜というページに〜という記述があり、特許を侵害してしまわないか心配だ。 - クライアント側で特定の暗号を使用しないように制御する方法はあるか? |
|
RSAもいいけど楕円曲線暗号もね。 というわけで、Rubyで素数位数の群をもつ楕円曲線を生成するスクリプトを組んでみました。 |
|
まだまだSSLを思考錯誤中です。 「SSL/TLS でアクセスしてみよう (2)」に記載されているサンプルについて 注意して頂きたい事があります。 HTTPSに接続後のサーバ証明書のsubjectとissuerを出力する部分で、 メモリーリークが発生する様です。 具体的には、 132: str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0); と 135: str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0); の返り値strそれぞれを OPENSSL_free( str )すればメモリーリークは直りました。 OpenSSLのバージョンは0.9.7aです。 OpenSSLドキュメントを見ても該当関数の事が記載されていなかったので 内部でアロケートしているかどうかソースを追っかけないと判りませんでした。 |
|
>>3882 ニッタン > HTTPSに接続後のサーバ証明書のsubjectとissuerを出力する部分で、 > メモリーリークが発生する様です。 ありがとうございます。 The functions X509_NAME_oneline() and X509_NAME_print() are legacy functions ということなので、X509_NAME_oneline() を使うのはやめて、 X509_NAME_print_ex() に変更しました。XN_FLAG_RFC2253 に したのは特に意味はありません。 # http://x68000.q-e-d.net/~68user/net/ssl-2.html |
|
ごもっとなご意見です。いろいろ推測させてしまったようです。 すみませんでした。 68userさんの推測とおり、 ・SSL対応のWebクライアントを作っています。 ・(Open)SSLの実装では特定の暗号化ロジックを使わないようしたい。 公開鍵の暗号化としてRSAを使いたいが有効鍵ビットは512としたい 共有鍵の暗号化としてRC4を使いたいが有効鍵ビットは40としたい これまでに以下の情報をご提供いただきました。 1.使用したい暗号化ロジックは SSL_CTX_set_cipher_list()で指定 2.暗号化方式として特定のロジックを使用禁止にしたいのであれば コンパイルオプションを設定すればよい について、有効鍵ビットを意識した設定は可能なのでしょか いろんなサンプルを見ましたが、方式の設定はあっても鍵長まで意識 したものが見つかりませんでした。 また、SSL_CTX_set_cipher_list()での設定は必須になるのでしょうか。 なかなかイメージがわきません。よろしくお願いします。 |
|
>>3884 jeiu > 公開鍵の暗号化としてRSAを使いたいが有効鍵ビットは512としたい > 共有鍵の暗号化としてRC4を使いたいが有効鍵ビットは40としたい では http://www21.ocn.ne.jp/~k-west/SSLandTLS/rfc2246-Ja.txt の RSA_EXPORT_WITH_RC4_40_MD5 で決まりでしょう。RSA かつ RC4 の 40bit となればこれしか選択肢がありません。 「RSA の鍵長 512bit 以下」という要件についてですが、これは 上記 RFC の 7.4.3. ServerKeyExchangeメッセージ ServerKeyExchangeメッセージは (略) 以下の鍵交換方式で使用される。 RSA_EXPORT (サーバ証明書の公開鍵が512ビットより長いとき) (略) 注: 現在の米国輸出法では、米国から輸出したソフトウェアにおいては、512 ビットより長いRSAのモジュラスを鍵交換において使用してはならない ことになっている。このメッセージを送信した場合、証明書内に含まれ ている512ビットより長いRSA鍵は、RSA_EXPORT鍵交換方式用の、512ビット 以下の長さを持つ一時的RSA鍵に署名するのに使用される。 で自然とクリアできます。 結局、ciphers(1) に SSL_RSA_EXPORT_WITH_RC4_40_MD5 EXP-RC4-MD5 とあるので SSL_connect() の前に if ( SSL_CTX_set_cipher_list(ctx, "EXP-RC4-MD5") == 0 ){ /* error */ } という処理を入れればよいでしょう。 |
|
68userさんのサイトで勉強させてもらってます。 http://x68000.q-e-d.net/~68user/net/rfc.html こちらのページの、POPの「日本語訳」のところがリンクが失敗してる ようですので、お知らせしておきます。 |
|
>>3886 kawa > http://x68000.q-e-d.net/~68user/net/rfc.html > こちらのページの、POPの「日本語訳」のところがリンクが失敗してる > ようですので、お知らせしておきます。 修正しました。ご連絡ありがとうございました。 |
|
自前parseルーチンで以下の様な処理をしています。 foreach(split(/&/, $query)){ my($name, $value) = split(/=/, $_); 〜日本語処理とかお約束の処理〜 # %FORMに格納 if(exist $FORM{$name}){;#既に以前の$nameが有れば(2回目以降) push($FORM{$name}, $value);#@{$FORM{$name}}の配列に格納 }else{ $FORM{$name} = $value;#初めての出現ならば通常通りに格納 } } 細かい部分は省略してますが、例えば checkbox などで、 chbox1&val1&chbox1&val2&chbox1&val3 の様なデータが来た場合、 $ALL_VALUE = $FORM{chbox} . " @{$FORM{chbox}}"; として、 $ALL_VALUE = 'val1 val2 val3' となる事を確認しています。 しかしなぜか、元のデータが複数の時の動作が理解できないのですが、 自分の理解が甘いような気もするので、ぜひとも動作の解説をしもらえない でしょうか? 以下は確認用のサンプルです。2行目のコメントを外して違いを確認ください。 データの内容によって結果が違います。 変数の内容が判りやすいように print 文を入れています。 $query=qq(cbox1=1&cbox1=2&cbox1=3&cbox2=1&cbox2=2&cbox2=3); #$query=qq(cbox1=1&cbox1=2&cbox1=3&cbox2=a&cbox2=b&cbox2=c); foreach(split(/&/, $query)){ my($name, $value) = split(/=/, $_); print qq($name=[$value]\n); if(exists $FORM{$name}){ push(@{$FORM{$name}}, $value); print qq( ->push:<$name>=[$value] count:). $#{$FORM{$name}} . qq(\n); }else{ $FORM{$name} = $value; } } print qq(Result1:[$FORM{'cbox1'} @{$FORM{'cbox1'}}]\n); print qq(Result2:[$FORM{'cbox2'} @{$FORM{'cbox2'}}]\n); 無名配列が $value の内容によって識別できていないように見えます。 Windows版とLinux版のそれぞれ 5.6.1 で確認しました。 |
|
書き忘れましたが perl でのお話です。 |
|
>>3888 スナフキン $query=qq(cbox1=1&cbox1=2&cbox1=3&cbox2=1&cbox2=4&cbox2=5); foreach (split(/&/, $query)){ my($name, $value) = split(/=/, $_); print qq($name=[$value]\n); if (exists $FORM{$name}){ push(@{$FORM{$name}}, $value); print "\@{$FORM{$name}}=@{$FORM{$name}}\n"; } else { $FORM{$name} = $value; } } print "\@1=@1\n"; cbox1=[1] cbox1=[2] @{1}=2 cbox1=[3] @{1}=2 3 cbox2=[1] cbox2=[4] @{1}=2 3 4 cbox2=[5] @{1}=2 3 4 5 @1=2 3 4 5 というわけで、最初のループで $FROM{$name} には 1 が入り、 @{$FORM{$name}} はシンボリックリファレンスと解釈され、結局 @1 に push しているわけです。 結局は一度目のループとそれ以降のループを分けず、常に push(@{$FORM{$name}}, $value); すればよいと思いますが、そもそも何をやりたかったのかによりますかね。 |
|
!!!なんとなるほど!シンボリックリファレンスと解釈されたとは・・・ すばやい回答大変助かりました。ありがとうございます。 このルーチンはいくつかある他のプログラムの一部なんですが、既に$FORM{〜} でアクセスする箇所が沢山有ったので、それらを変更する事なくという部分に こだわりすぎました。 cgi-lib.pl とかを見るとparse時に \0 をセパレータにしてスカラーに入れて いますが、そうではなく同名変数の配列にぶち込んじゃおうと思ったのですが 他の方法をかんがえてみます。 |