0

TripleDESCryptoServiceProviderを使用してデータを復号化するときに問題が発生します。問題は、復号化された値に、元の値のほかに、最後にいくつかの追加の奇妙な文字が含まれていることです

たとえば、暗号化する「rastko」を提供すると、後でこの「rastko⥊㮶」のような復号化が行われます。他の値の場合、「ダミー」文字の数が異なる可能性があります。または、場合によっては正確な値を取得します。

次に、暗号化されたすべてのデータのバイト配列サイズが8で割り切れることがわかりました。提供されたデータは8で割り切れる値で丸められているようです。元のエンコードされた値が8で割り切れる場合にのみ、復号化によって適切な値が取得されます。 。

これが私が使用しているメソッドです:

        public static byte[] EncryptPassword(string password, out byte[] cryptoKey, out byte[] cryptoIV)
    {
        try
        {
            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            byte[] unicodePassword = unicodeEncoding.GetBytes(password);
            byte[] encryptedPassword;

            using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
            {
                tripleDes.Key = GetCryptoKey();
                tripleDes.Mode = CipherMode.CBC;
                tripleDes.Padding = PaddingMode.PKCS7;
                cryptoKey = tripleDes.Key;
                cryptoIV = tripleDes.IV;

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    ICryptoTransform cryptoTransform = tripleDes.CreateEncryptor();

                    using (
                        CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(unicodePassword, 0, unicodePassword.Length);
                        ////cryptoStream.FlushFinalBlock();
                    }

                    encryptedPassword = memoryStream.ToArray();
                }
            }

            return encryptedPassword;
        }
        catch (Exception ex)
        {
            throw new Exception("Password encryption failed !", ex);
        }
    }

    public static string DecryptPassword(byte[] encryptedPassword, byte[] cryptoKey, byte[] cryptoIV)
    {
        try
        {
            UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
            string readablePassword;

            using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
            {
                tripleDes.Key = cryptoKey;
                tripleDes.IV = cryptoIV;
                tripleDes.Mode = CipherMode.CBC;
                tripleDes.Padding = PaddingMode.PKCS7;

                // Create a new MemoryStream using the passed 
                // array of encrypted data.
                using (MemoryStream memoryStream = new MemoryStream(encryptedPassword))
                {
                    // Create crypto transform that defines the basic operations of cryptographic transformations.
                    ICryptoTransform cryptoTransform = tripleDes.CreateDecryptor();

                    // Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
                    using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
                    {
                        decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
                        ///decryptoStream.FlushFinalBlock();
                    }

                    byte[] decryptedPassword = memoryStream.ToArray();

                    //Convert the buffer into a string and return it.
                    readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
                }
            }

            return readablePassword;
        }
        catch (Exception ex)
        {
            throw new Exception("Password decryption failed !", ex);
        }
    }

    private static byte[] GetCryptoKey()
    {
        UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
        string plainKey = "rastkoisajev2310982josipasenera153";
        byte[] encodedKey = unicodeEncoding.GetBytes(plainKey);

        // Prepares 192 bit key
        byte[] preparedKey = new byte[24];
        Array.Copy(encodedKey, preparedKey, 24);

        return preparedKey;
    }

テスト呼び出しの例は次のとおりです。

       private static void CryptoTest()
    {
        string password = "rastko";

        byte[] cryptoKey;
        byte[] cryptoIV;

        byte[] encryptedPassword = Crypto.EncryptPassword(password, out cryptoKey, out cryptoIV);

        string decryptedPAssword = Crypto.DecryptPassword(encryptedPassword, cryptoKey, cryptoIV);
    }

私はセキュリティの経験がありません。私が見ているのは、IVベクトルが8バイトサイズであり、私が見つけたように、それはIVサイズの8倍であるBlockSizeに関連しているということです。IVベクター用のTripleDESCryptoServiceProviderは8バイトの値を使用しています。これは変更できません。

私がしなければならないことを教えてください、または私は何か間違って書いたのですか?

4

3 に答える 3

1

DESは64ビットのブロック暗号です。64ビット(= 8バイト)ブロックにきれいに分割されないテキストは、整数のブロックを構成するためにパディングする必要があります。暗号化と復号化のパディングを設定する必要があります。両端を制御できる場合は、PKCS#5パディングを使用して暗号化と復号化を行います。復号化側のみを制御できる場合は、暗号化側に使用しているパディングを尋ねて、それを期待してください。

于 2012-08-05T17:06:51.163 に答える
0

通常、パスワードを暗号化することはできません。代わりにPBKDF2を使用してください。パスワードとキーを混同しないでください!

CryptoStreamsが閉じられるかフラッシュされることを確認してください。

http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.flushfinalblock.aspx

そうしないと、パディング/アンパディングが実行されない可能性が高く、代わりにゴミ箱が表示されます。

于 2012-08-05T15:59:56.757 に答える
0

詳細な調査の結果、問題の解決策が見つかりました。復号化ロジックを少し変更しました。

DecryptPasswordメソッドのこの部分の代わりに:

 // Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
                using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
                {
                    decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
                    ///decryptoStream.FlushFinalBlock();
                }

                byte[] decryptedPassword = memoryStream.ToArray();

                //Convert the buffer into a string and return it.
                readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
            }

現在、CryptoStreamの読み取りロジックを使用しており、null許容文字を削除しています。今はこんな感じです:

                        // Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
                    using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
                    {
                        // Create buffer to hold the decrypted data.
                        byte[] fromEncrypt = new byte[encryptedPassword.Length];

                        decryptoStream.Read(fromEncrypt, 0, fromEncrypt.Length);

                        //Convert the buffer into a string and return it.
                        readablePassword = unicodeEncoding.GetString(fromEncrypt);
                        readablePassword = readablePassword.Replace("\0", string.Empty);
                    }

これは私にとって完璧に機能します!いつもありがとうございました。

于 2012-08-06T14:37:53.463 に答える