公開鍵の秘密 -3-2007/02/08 17:58

... さらにつづく。

早速 OpenSSH 4.5p1 のソースを落としてきて眺めてみた。

sshconnect2.c の userauth_pubkey() 関数あたりが、実際に公開鍵認証を実行しているクライアント側のコードのようである。

userauth_pubkey() の中盤あたりはこうなっている。

   1121                 if (id->key && id->key->type != KEY_RSA1) {
   1122                         debug("Offering public key: %s", id->filename);
   1123                         sent = send_pubkey_test(authctxt, id);
   1124                 } else if (id->key == NULL) {
   1125                         debug("Trying private key: %s", id->filename);
   1126                         id->key = load_identity_file(id->filename);
   1127                         if (id->key != NULL) {
   1128                                 id->isprivate = 1;
   1129                                 sent = sign_and_send_pubkey(authctxt, id);
   1130                                 key_free(id->key);
   1131                                 id->key = NULL;
   1132                         }
   1133                 }

つまり、ここまでの流れの中で id->key に値が設定されていないと、公開鍵が見つからなかったと判断して、load_identity_file()関数を呼んで秘密鍵を得る。(1126行目)。引数の id->filename は ssh コマンドを実行したときに -i オプションで渡したファイル名がセットされている。

id->key に秘密鍵を読み込んだところで、sign_and_send_pubkey() を呼び出す。この関数は同じ sshconnect2.c に定義されていて、サーバーへの接続はこの関数の中で行われる。sign_and_send_pubkey() では、

    869         if (key_to_blob(id->key, &blob, &bloblen) == 0) {
    870                 /* we cannot handle this key */
    871                 debug3("sign_and_send_pubkey: cannot handle key");
    872                 return 0;
    873         }

と、869行目で key_to_blob() 関数に読み込んだ秘密鍵を渡している。

key_to_blob() 関数は id->key に格納されている秘密鍵から "blob"へと変換する。blob とは「ひとかたまり」を意味する英単語で、データベースの Binary Large Object のことではない。

その key_to_blob() は key.c で定義されている。実際に秘密鍵から blob に変換する部分のコードは次の通りだ。

   757         switch (key->type) {
    758         case KEY_DSA:
    759                 buffer_put_cstring(&b, key_ssh_name(key));
    760                 buffer_put_bignum2(&b, key->dsa->p);
    761                 buffer_put_bignum2(&b, key->dsa->q);
    762                 buffer_put_bignum2(&b, key->dsa->g);
    763                 buffer_put_bignum2(&b, key->dsa->pub_key);
    764                 break;
    765         case KEY_RSA:
    766                 buffer_put_cstring(&b, key_ssh_name(key));
    767                 buffer_put_bignum2(&b, key->rsa->e);
    768                 buffer_put_bignum2(&b, key->rsa->n);
    769                 break;

ここで問題となるのが 767行目と 768行目の key->rsa->e と key->rsa->n だ。RSA とはつまりは秘密鍵と公開鍵の二つの非対称鍵を使うしくみなのだが、rsa->e は encryption exponent (暗号化指数)、rsa->n は RSA moduli (OpenSSH では public moduli: 係数) を意味する。rsa->e と rsa->n の組み合わせが公開鍵となり、秘密鍵は rsa->d (decryption exponent: 復号化指数) と rsa->n の組み合わせになる。

上記の流れで行くと、userauth_pubkey() で秘密鍵を id->key にロードし、さらに key_to_blob() で id->key にセットされている秘密鍵から暗号化指数 rsa->e と係数 rsa->n を読み出している。

さて。困った。

秘密鍵がもっているのは、復号化指数 (rsa->d)と係数(rsa->n)ではないのか?

userauth_pubkey() で秘密鍵を読み出しておきながら、つづく key_to_blob() でその秘密鍵から暗号化指数 (rsa->e)を読み出せているリクツはなんだろう。

load_identity_file() で id->key になにをロードしているのか調べる必要がある。

まだつづく... が...

どうも、RSA の基本からやりなおさなければだめなようだ...

コメント

トラックバック