2

次の2つの方法があります。

1番目の方法

  //SymmetricEncryting 
 private byte[] SymmetricEncrypt()
  {
  try
      {
        //Get Byte Value 
        byte[] x= Encoding.Default.GetBytes("Test");

        byte [] y;

        //Create Symmetric Key Encription
        RijndaelManaged rijndaelManaged = new RijndaelManaged();

        //GetSymmetricPublicKey
        _symmetricPublicKey = rijndaelManaged.Key;

        //Get Symmetric Public IV
        _symmetricPublicIv = rijndaelManaged.IV;

        using (MemoryStream memoryStream = new MemoryStream(x))
        {
            //Start EncriptionProcess
            var cryptoStream = new CryptoStream(memoryStream,
                                                rijndaelManaged.CreateEncryptor
                                                 (_symmetricPublicKey,
                                                 _symmetricPublicIv),
                                                CryptoStreamMode.Write);

            cryptoStream.Write(x, 0, x.Length);

            // Complete the encryption process
            //cryptoStream.FlushFinalBlock();

            y= memoryStream.ToArray();


        }

        return y;
    }
    catch (Exception)
    {
        throw;
    }
}

2番目の方法

private string Decrypt(
    byte[] y,
    byte[] symmetricPublicKey,
    byte[] symmtricPublicIv)
{
    try
    {
        //Create the Key Container
        CspParameters cspParameters = new CspParameters();

        //Get the AsyPrivate and Public key from the Container
        cspParameters.KeyContainerName = "Keys";


        var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);

        //Decrypt and get the Symmetric Public key
        var decryptedSymmetricPubk = rsaCryptoServiceProvider.Decrypt(symmetricPublicKey, false);

        //Decrypt and get the Symmetric Public IV
        var decryptedSymmetricPubIv = rsaCryptoServiceProvider.Decrypt(symmtricPublicIv, false);

        //Create RijndaelManaged object to do the Symmtric dycrption
        RijndaelManaged rijndaelManaged = new RijndaelManaged();

        //Create cryptostream using decrypted symmetric Public Key and IV
        ICryptoTransform iCryptoTransform = rijndaelManaged.CreateDecryptor(decryptedSymmetricPubk,
                                                                            decryptedSymmetricPubIv);
        //Create a memory stream 
        using (MemoryStream memoryStream = new MemoryStream(y))
        {

            var cryptoStream = new CryptoStream(memoryStream, iCryptoTransform, CryptoStreamMode.Read);

            byte[] z= new byte[y.Length];

            cryptoStream.Read(z, 0, z.Length);

            //cryptoStream.FlushFinalBlock();

            //Convert byte array to string
            var x= System.Text.Encoding.Default.GetString(z);

            return x;
        }
    }
    catch (Exception)
    {
        throw;
    }

コードにあるように、対称暗号化を使用して文字列を暗号化しようとしています。すでに作成した非対称公開鍵を使用して対称公開鍵とIvを暗号化します。次に、暗号化された文字列を復号化しようとしています。

問題1暗号化と復号化の両方 を行う目的は何ですかcryptoStream.FlushFinalBlock();。msdnから学んだように、cyptostreamで実行されているプロセスが終了します。

問題2 行のコメントを外すcryptoStream.FlushFinalBlock();と、例外がスローされます "Memory stream is not expandable."。しかし、私がその行にコメントすると、それはうまく機能し、バイト配列を返します。

問題3 ただし、2番目のメソッドは、"system.security.cryptography.cryptographicexception length of the data to decrypt is invalid行cryptoStream.Read(z、0、z.Length);の実行時に例外をスローします。

デバッグでこれらのエラーの実際の原因を見つけることができませんでした。また、Googleで検索しましたが、残念ながら解決策が見つかりませんでした。誰かが答えを説明できますか?

4

2 に答える 2

9

PKCSパディングを使用して暗号化しています(これがデフォルトです)。AES / Rijndaelはブロック暗号です。つまり、一度に暗号化できるのは16バイトのブロックのみです。ブロック暗号が任意のサイズのデータ​​を暗号化できるようにするために、パディングアルゴリズムを使用します。PKCSパディングは、暗号化時に1〜16バイトを最後に追加し、復号化時にそれらを削除することで機能します。パディングの長さは、パディング自体にエンコードされます。

FlushFinalBlockCryptoStreamに受信データがもうないことを通知し、パディングを追加する必要があることを暗号化するときに必要です。CryptoStreamを読み取りモードで使用している場合は、これは必須ではなく、使用しないでください。

最初の例外は、MemoryStreamのバッキングストアとしてplaintext-arrayを使用しているためです。パディングのため、暗号化は平文よりも大きくなります。

2番目の例外は、FlushFinalBlockステートメントを削除したことと、MemoryStreamのサイズを変更して正しい長さの配列を作成することが許可されていないことです。暗号化されたデータは常に16バイトの倍数である必要がありますが、MemoryStreamはを再利用するためxyと同じ長さになりますがx、これは常に有効な長さではありません。

解決策は次のとおりです。

  1. FlushFinalBlockSymmetricEncryptで使用します。
  2. using (MemoryStream memoryStream = new MemoryStream(x))using (MemoryStream memoryStream = new MemoryStream(y))に置き換えusing (MemoryStream memoryStream = new MemoryStream())ます。これにより、MemoryStreamsのサイズを自由に変更できます。
于 2012-05-30T05:55:02.673 に答える
0

奇妙なことに、復号化するときにも書き込み操作を実行するだけでうまくいきます。何かのようなもの:

var decryptMemoryStream = new MemoryStream();
var decryptStream = new CryptoStream(decryptMemoryStream, iCryptoTransform , CryptoStreamMode.Write);

//write the unencrypted data array to the stream
decryptStream.Write(y, 0, y.Length);
decryptStream.Flush();
decryptStream.Close();

var decryptedData = decryptMemoryStream.ToArray();
于 2018-03-05T00:06:41.703 に答える