2

Flex クライアントと C# で記述された Web サービス間の RSA 暗号化/復号化メカニズムの設定に問題があります。アイデアは次のとおりです。flex から一部のテキストを暗号化し、Web サービスから復号化します。Google の as3crypto ライブラリを使用しています。テキストを適切に暗号化/復号化しています。また、適切に暗号化/復号化するための Web サービス側のコードもあります。私の問題はそれらを同期することです-基本的に公開鍵をフレックスに共有し、秘密鍵をWebサービスに保持します。

私のフレックス「暗号化」関数は、テキスト暗号化を行うために RSA のモジュラスと指数を使用します。これらのモジュラスと指数の属性を Web サービスの RSACryptoServiceProvider から取得して、同じ標準を使用するにはどうすればよいですか。Web サービスから RSAKeyInfo.Modulus RSAKeyInfo.Exponent を試し、それらをフレックス クライアントに送りました。フレックスで暗号化を行った後、暗号テキストを取得し、それを Web サービスの復号化メソッドにフィードしましたが、「不良データ」エラー メッセージが表示されます。

System.Security.Cryptography.CryptographicException: Bad Data.

   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._DecryptKey(SafeKeyHandle hPubKey, Byte[] key, Int32 dwFlags)
   at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
   at Microsoft.Samples.Security.PublicKey.App.RSADecrypt(Byte[] DataToDecrypt, RSAParameters RSAKeyInfo, Boolean DoOAEPPadding) in C:\Users
\Me\Desktop\After Release\5-24-2011-webServiceCrypto\publickeycryptography\CS\PublicKeyCryptography\PublicKey.cs:line 219
Encryption failed.

両方が同じバイト 64 または 128 バイトの暗号化を使用していることを確認するにはどうすればよいですか。つまり、flex からの入力は、Web サービス RSACryptoServiceProvider の復号化メソッドによって期待されるものに適合する必要があります。(サイズが問題かもしれないと思いますが、そうではないかもしれません - 私は迷っています)

これがコードです。最初のフレックスクライアントに続いてWebサービスのC#コードです

private function encrypt():void {
                var rsa:RSAKey = RSAKey.parsePublicKey(getModulus(), getExponent());
                trace("Modulus Lenght: " + getModulus().length);
                trace("Exponent Lenght : " + getExponent().length);
                var data:ByteArray = getInput();  //returns byteArray of plainText
                var dst:ByteArray = new ByteArray;
                rsa.encrypt(data, dst, data.length);
                trace("Enc Data: " + dst.toString() );
                currentResult = Hex.fromArray(dst);
                encryptedText = currentResult;
                trace("Encrypted:: " + currentResult);
            }

            //For testing purposes
            private function decrypt():void {
                var rsa:RSAKey = RSAKey.parsePrivateKey(getModulus(), getExponent(), getPrivate(), getP(), getQ(), getDMP1(), getDMQ1(), getCoeff());
                var data:ByteArray = Hex.toArray(encryptedText);
                trace("Byte array: " + data.toString());
                var dst:ByteArray = new ByteArray;
                rsa.decrypt(data, dst, data.length);
                decryptedText = Hex.fromArray(dst);
                trace("Decrypted text: " + Hex.toString(decryptedText));
            }

また、Web サービス部分は次のとおりです。

       try
        {
            //Create a UnicodeEncoder to convert between byte array and string.
            UnicodeEncoding ByteConverter = new UnicodeEncoding();

            //Create byte arrays to hold original, encrypted, and decrypted data.
            byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt");
            byte[] encryptedData;
            byte[] decryptedData;

            //Create a new instance of RSACryptoServiceProvider to generate
            //public and private key data.
            using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
            {
                //Pass the data to ENCRYPT, the public key information 
                //(using RSACryptoServiceProvider.ExportParameters(false),
                //and a boolean flag specifying no OAEP padding.
                encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);
                //Pass the data to DECRYPT, the private key information 
                //(using RSACryptoServiceProvider.ExportParameters(true),
                //and a boolean flag specifying no OAEP padding.
                decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true), false);
                //Display the decrypted plaintext to the console. 
                Console.WriteLine("\n\nDecrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
            }
        }

static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
    {
        try
        {
            byte[] encryptedData;
            //Create a new instance of RSACryptoServiceProvider.
            using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
            {

                //Import the RSA Key information. This only needs
                //toinclude the public key information.
                RSA.ImportParameters(RSAKeyInfo);

                //Encrypt the passed byte array and specify OAEP padding.  
                //OAEP padding is only available on Microsoft Windows XP or
                //later.  
                encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
            }
            return encryptedData;
        }
        //Catch and display a CryptographicException  
        //to the console.
        catch (CryptographicException e)
        {
            Console.WriteLine(e.Message);

            return null;
        }

    }


 static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
    {
        try
        {
            Console.WriteLine("Modulus Lenghth :" + RSAKeyInfo.Modulus.Length);
            Console.WriteLine("Exponent Length :" + RSAKeyInfo.Exponent.Length);
            byte[] decryptedData;
            //Create a new instance of RSACryptoServiceProvider.
            using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
            {
                //Import the RSA Key information. This needs
                //to include the private key information.
                RSA.ImportParameters(RSAKeyInfo);

                //Decrypt the passed byte array and specify OAEP padding.  
                //OAEP padding is only available on Microsoft Windows XP or
                //later.  
                decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
            }
            return decryptedData;
        }
        //Catch and display a CryptographicException  
        //to the console.
        catch (CryptographicException e)
        {
            Console.WriteLine(e.ToString());

            return null;
        }

    }

この RSA セットアップが正しいかどうかはよくわかりません...どんなコメント/アドバイス/または推奨される解決策も歓迎します、ありがとう

4

3 に答える 3

3

ユーレカ!ユーレカ!わかった。

問題は、Web サービスからの復号化の後、暗号化されたバイト配列が間に 0 を逃したため、文字列に変更すると読み取り不能になる「????????」でした。文章。したがって、 paddWithZeros() 関数を配置して、復号化されたバイト配列にバイト間に 0 を埋め込むと、機能しました。

ケビンに感謝します。あなたのソリューションは、私が何を考慮すべきかについての洞察を与えてくれました。そのため、復号化中にパラメータ fOAEP を false に指定して、パディングに PKCS#1 を使用します (両方のライブラリが同じ標準を使用するようにします)。

RSA.Decrypt(DataToDecrypt, DoOAEPPadding); // DoOAEPPadding = false

私が得ていた別のエラーはBad Data例外です。これは、RSA cryptoServiceProvider のパラメーター (モジュラスと指数) を actionScript メソッドに共有したときに修正されました。

また、C# RSA 属性 (Modulus n、Exponent e、Private d など) の byte[] 配列を 16 進文字列に変更して、as3crypto ライブラリと共有できるようにしました。

私にとって何がうまくいったかを共有したいと思います。他の時間を節約します。

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

    <fx:Script>
        <![CDATA[
            import com.hurlant.crypto.Crypto;
            import com.hurlant.crypto.rsa.RSAKey;
            import com.hurlant.crypto.symmetric.ICipher;
            import com.hurlant.crypto.symmetric.IPad;
            import com.hurlant.util.Hex;

            private var currentResult:String;
            private var encryptedText:String;
            private var decryptedText:String;

            private function encrypt(plainText:String):String {
                var rsa:RSAKey = RSAKey.parsePublicKey(getModulus(), getExponent());
                var data:ByteArray = Hex.toArray(Hex.fromString(plainText));  //returns byteArray of plainText
                var dst:ByteArray = new ByteArray;
                rsa.encrypt(data, dst, data.length);
                currentResult = Hex.fromArray(dst);
                encryptedText = currentResult;
                trace ("Cipher: " + currentResult);
                return currentResult;
            }

            private function getInput():ByteArray {
                return null;
            }

            private function getModulus():String {
                return "b6a7ca9002b4df39af1ed39251a5d"; //read this value from web service.
            }

            private function getExponent():String {
                return "011"; //read this value from web service.
            }

            //For debugging and testing purposes
            // private function decrypt(cipherText:String):String {
                // var rsa:RSAKey = RSAKey.parsePrivateKey(getModulus(), getExponent(), getPrivate(), getP(), getQ(), getDMP1(), getDMQ1(), getCoeff());
                // var data:ByteArray = Hex.toArray(cipherText);
                // var dst:ByteArray = new ByteArray;
                // rsa.decrypt(data, dst, data.length);
                // decryptedText = Hex.fromArray(dst);
                     //trace('decrypted : ' + decryptedText);
                // return Hex.toString(decryptedText);
            // }

        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <mx:VBox >
        <s:Button label="Encrypt Text" click="encrypt('my plain text')" />
        <s:Button label="Decrypt Text" click="decrypt({encryptedText})" />
    </mx:VBox>
</s:Application>

復号化の Web サービス部分は次のようになります。

 static public string RSADecrypt(string cipherText)
    {
        UnicodeEncoding ByteConverter = new UnicodeEncoding();
        byte[] DataToDecrypt = StringToByteArray(cipherText);
        bool DoOAEPPadding = false;
        try
        {
            byte[] decryptedData;
            using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
            {
                KeyInfo keyInfo = new KeyInfo();
                RSAParameters RSAKeyInfo = keyInfo.getKey();
                RSA.ImportParameters(RSAKeyInfo); 
                decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
            }
            byte[] paddedOutput = paddWithZeros(decryptedData); //to sync with as3crypto
            return (ByteConverter.GetString(paddedOutput));

        }catch (CryptographicException e)
        {
            //handle error
            return null;
        }
    }

RSAのパディングスキームについて読んで、誤解がないかどうかを確認します。

ありがとう

于 2011-05-26T18:54:53.377 に答える
1

複雑すぎるようです。私は以前にいくつかの高セキュリティシステムに取り組んだことがありますが、これはばかげています。入力したテキストをユーザーに知られたくない場合を除いて、送信するテキストにこの種の暗号化が必要なのはなぜですか。

バイナリデータ形式(AMF)を使用した実際の転送プロトコル(HTTPを想像します)には、強力なSSLキー(IE6では256ビットが最大です。512を使用できますが、新しいブラウザーとのみ互換性があります)を使用するだけで問題ありません。あなたのシステムが暗号化テキストの使用を活用するためにそれほど重要であるとは思えません。

于 2011-05-25T13:33:20.027 に答える
1

as3crypto と JAVA Web サービスを使用しています。ここにいくつかの考えがあります:

を。openssl を介して RSA 公開鍵と秘密鍵を生成しました

b. 私のクライアントは、アプリケーションの起動時にパブリック .cer ファイルをロードします (生成されたキーからそれらをハードコーディングした場合も機能します)。

var pemString : String = new String(data.target.data);
var x509Cert : X509Certificate = new X509Certificate(pemString);
var publicRSAKey : RSAKey = x509Cert.getPublicKey();

c. 文字列を暗号化する

var inputByteArray : ByteArray = Hex.toArray(Hex.fromString(inputString));
var outputByteArray : ByteArray = new ByteArray();
appSettingsModel.publicRSAKey.encrypt(inputByteArray, outputByteArray, inputByteArray.length);

d. 私は Java 側のことを書きませんでしたが、とにかく Java を使用していません。as3crypto はデフォルトで PKCS1 パディングを使用することを知っています。

RSAKEY.as

private function _encrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
            // adjust pad if needed
            if (pad==null) pad = pkcs1pad;

これは変更できますが、まだ試していません。コードに基づいて、OAEP スキームで復号化しようとしているように見えますが、そのブール値をどのように設定しているかはわかりません。bool が false の場合に使用されているパディング スキームを確認し、パディング戦略に一致するように一方または他方を変更してみてください。

于 2011-05-25T12:41:39.757 に答える