1

クライアントに送信する前に、RSAキーを.NETで使用されるXML形式に変換するJavaで記述されたサーバーがあります。

public String getPublicKeyXML() {
    try {
        KeyFactory factory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec publicKey = factory.getKeySpec(this.keyPair.getPublic(), RSAPublicKeySpec.class);

        byte[] modulus = publicKey.getModulus().toByteArray();
        byte[] exponent = publicKey.getPublicExponent().toByteArray();

        String modulusStr = Base64.encodeBytes(modulus);
        String exponentStr = Base64.encodeBytes(exponent);

        String format = 
            "<RSAKeyValue>" +
                "<Modulus>%s</Modulus>" +
                "<Exponent>%s</Exponent>" +
            "</RSAKeyValue>";

        return String.format(format, modulusStr, exponentStr);
    } catch (Exception e) {
        this.server.logException(e);
        return "";
    }
}

次に、C# で記述されたクライアントがキーを読み込み、それを使用して 256 ビットの AES キーを暗号化します。

    public static byte[] encrypt(string xmlKey, byte[] bytes)
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(xmlKey);
        byte[] cipherBytes = rsa.Encrypt(bytes, false);
        rsa.Clear();
        return cipherBytes;
    }

サーバーは、秘密の RSA キーを使用して AES キーを復号化することになっています。

public byte[] decrypt(byte[] data) {
    try {
        PrivateKey privateKey = this.keyPair.getPrivate();
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] cipherData = cipher.doFinal(data);
        return cipherData;
    } catch (Exception e) {
        this.server.logException(e);
        return new byte[0];
    }
}

ただし、サーバーは「データは 384 バイトを超えてはなりません」というエラーで失敗します。復号化するデータを見てみると、385 バイトであることがわかりました。RSA キーの長さを増やしてみましたが、クライアントからの暗号化されたデータは 513 バイトですが、サーバーはデータが 512 バイトを超えてはならないことを通知します。暗号化されたデータが常に予想よりも 1 バイト長いのはなぜですか?

編集:

サーバーからクライアントに送信される XML 形式のキーの例を次に示します。

<RSAKeyValue><Modulus>ANsMd2dCF6RsD5v5qjlHEjHm0VWD99gSYHP+pvyU8OgNL9xM5+o+yMAxWISOwMii9vJk1IzYGf18Fj2sMb5BsInlG2boZHb6KHh7v8ObPa4MuwB/U63i8AVU3N/JTugaPH0TKvo1WNUooXEHT23nOk+vh1QipzgKQYGl68qU35vKmpNAa79l1spXA66LckTWal4art9T08Rxgn9cMWujlF+wh9EQKQoxxgj4gCoXWRDTFYjRo/Mp5xDPwNjloTs/vFCPLvY7oI+lVrHhrPyz1R473ZuEhZm+rSeGBcY9I8vhg0AIixN7KYBLhrIecmqoNZHi6LohjD2F9zhdLaTU0IIU8eeKpbEZ5eB1kYngMONBq3A/IoG0Qa/7EcSAMMspBEObffK9kCNzvnbFg5wLuy8EHNaK3nmnuTppgCwCyNqZyHeAbZaUBjNguLhHtqkHFiPJ063Xesj9UbSsCmlBliGTDXWfeJANnjGP6D3R+uLXVy9SZe+cY92JW3eZA2k//w==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

送信されたデータが受信されたデータと同じであることを確認しました。

最後のバイトをノックオフすると、BadPaddingException が発生します。また、最初のバイトをノックオフしようとしましたが、同じ結果になりました。

4

2 に答える 2

3

問題が見つかりました。BigInteger の toByteArray() 関数には、何らかの理由で先行ゼロが含まれていました。配列から先頭のゼロを削除したところ、魅力的に機能するようになりました!

于 2012-07-31T00:59:06.013 に答える
1

これで問題が解決するわけではありません (私はそれをテストしましたが役に立ちませんでした) が、RSACryptoServiceProviderはIDisposableインターフェイスを実装しているため、完了したら適切に破棄する必要があることに注意してください。C#encryptのメソッドは、次のように、もう少し適切に (そしてより簡潔に) 記述できます。

    public static byte[] encrypt(string xmlKey, byte[] bytes)
    {
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.FromXmlString(xmlKey);
            return rsa.Encrypt(bytes, false);
        }
    }
于 2012-07-30T22:01:32.790 に答える