3

クライアント/サーバー インフラストラクチャを使用してアプリケーションを構築しており、公開/秘密キー方式を使用して認証メカニズムを実装したいと考えています。

クライアントが秘密鍵を所有し、サーバーが公開鍵しか持っていないと仮定しましょう。認証中、クライアントは秘密鍵でメッセージに署名し、公開鍵で検証されるサーバーに送信します。検証が成功すると、クライアントは認証されます。

以下は、概念に慣れた JUnit テスト コードです。

@Test
public void testSignature() throws Exception {
    final String message = "Hello world is a stupid message to be signed";

    final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();

    final Signature privSig = Signature.getInstance("SHA1withRSA");

    privSig.initSign(keyPair.getPrivate());
    privSig.update(message.getBytes());

    byte[] signature = privSig.sign();

    final Signature pubSig = Signature.getInstance("SHA1withRSA");

    pubSig.initVerify(keyPair.getPublic());
    pubSig.update(message.getBytes());

    assertTrue(pubSig.verify(signature));
}

もちろん、これが機能するためには、サーバーとクライアントの両方がプレーン メッセージ (ダイジェスト) を所有している必要があります。

ここで私の質問は次のとおりです。署名に使用するのに適したメッセージ (ダイジェスト) は何ですか? たとえば、これは静的なハードコードされた文字列 (すべてのクライアントに使用される) である可能性がありますか?それとも、この概念に何らかのセキュリティ上の問題を課すことになるでしょうか? 静的な文字列が悪い場合、認証の前にランダムな文字列をネゴシエートするのは良い考えでしょうか? このランダムな文字列は、たとえば「セッション」キーとして使用でき、しばらくすると無効になります。

4

1 に答える 1

3

繰り返し攻撃の影響を受けやすいため、静的文字列は不適切です (署名付き文字列は毎回同じになります)。

ただし、以前に行われたことを再発明しているようです。証明書の使用は、信頼できる方法です。詳細については、次の例を参照してください: Java HTTPS クライアント証明書認証

自分で実装したい場合は、おそらく SSL の仕組みを調べて、それを模倣する必要があります。他のソリューションには、非常に特注でない限り、いくつかの欠陥がある可能性があります(たとえば、クライアントは、再利用されなかった共有静的文字列の1000のリストを保持し、サーバーは同じリストを持ち、何があったかを追跡しますまたは、以下のコメントで提案されているように、増加する共有番号を追跡します。)

于 2012-04-23T21:50:47.487 に答える