1

私はRSA事前共有キーを使用して、理想的にはトラストストアのシェナニガンを使用せずに通信しようとしています。

セットアップは基本的に次のようになります。

クライアント側にアプレットがあり、サーバー側にサーブレットがあります(duh :))

アプレットには、サーブレットのRSA公開鍵(Spub)がハードコーディングされています。

サーブレットには、ハードコーディングされた独自のRSA秘密鍵(Spriv)があります。

彼らは、ランダムなAES 256キー(セッションキー)を生成し、サーブレットの公開キー(ハードコーディングされている)で暗号化し、TCPソケットを介してサーブレットに接続し、RSA暗号化キーをサーブレットに送信します。セッションキーを使用して、このソケット接続が続く限り、このサーブレットとのさらなる通信に使用します。

私はむしろ、トラストストアなどをいじることなくこれをすべて実行したいと思います(結局のところ、事前共有されたハードコードされた公開鍵を可能にする比較的簡単なセットアップです)

自分自身を教育するためにどこから始めるべきかについての提案はありますか?

4

2 に答える 2

2

PublicKeyをビルドしてを使用することで低レベルの暗号化関数を使用できますがCipher、JSSE の使用を検討する価値があります。JSSE は、ソケットのコンテキスト内ですべてを提供します。さらに、SSL/TLS によって提供される暗号化は、ハンドシェイク中にネゴシエートされた共有キーを介して行われます (とりわけ、非対称暗号よりも高速です)。

その公開鍵を事前共有するための自己署名証明書を使用してトラストストアを構築できます。次のようにロードできます ( は であるInputStream必要はありませんFileInputStream。たとえば、メモリからコンテンツを読み取ることができます)。

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
InputStream is = ...
ks.load(is, null);
// or ks.load(is, "thepassword".toCharArray());
is.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

SSLSocketFactory = sslContext.getSocketFactory();
// ...

これが JSSE の通常の使用方法です。明示的な RSA 公開鍵で SSL/TLS を使用する場合はTrustManager、明示的な比較を ( を使用する代わりにTrustManagerFactory) 独自に実装する必要があります。これにより、コードが少し長く複雑になります。

これらすべてをアプレット内で実行すると、ソケット接続を行うためのアプレット許可システムに関してまだ問題が発生する可能性があります。アプレットでできることとできないことを参照してください。

于 2012-07-07T14:38:29.540 に答える
2

SSLは適切な方法であるというコメントには同意しますが、直接の質問に答えると、説明したスキームはかなり単純で、秘密を漏らしているようには見えません. ハードコーディングされた公開鍵に基づく、クライアントの RSA 部分の実装を次に示します。

// Hardcoded values extracted from getModulus of a generated KeySpec.
private static BigInteger mod = new BigInteger("113...");
private static BigInteger exp = new BigInteger("217...");

private PublicKey hardCodedKey() {
    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(mod, exp);
    KeyFactory keyFactory = null;
    PublicKey rsaKey = null;
    try {
        keyFactory = KeyFactory.getInstance("RSA");
        rsaKey = keyFactory.generatePublic(keySpec);
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
    return rsaKey;
}

private byte[] encrypt(PublicKey pubKey, byte[] plaintext) {
    try {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(plaintext);
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
}
于 2012-07-07T05:17:31.417 に答える