2

Entity Framework を使用して C# MVC アプリで暗号化されたデータベース フィールドがあります。その部分は、暗号化と復号化に問題なく機能します。SSRS レポートで復号化されたこのデータを示す必要があります。

Decrypt メソッドを使用して VB.Net に変換し、レポートのコード ビハインドに配置しました。StreamReaderのメソッドを呼び出すときにエラーが発生しますReadToEnd。既に閉じられているストリームを閉じようとすると問題が発生するという問題について、オンラインでいくつかの参考文献を見つけました。このストリームは 1 回だけ読み取られ、ストリーム全体を読み取っているため、その時点で閉じてはいけません。

Length - 1cryptoStream からバイトを読み取ろうとしましたが、エラーは発生しませんでした。バイトを読み取ろうとするとLength、同じエラーが発生します。1 バイトを除くすべてを読み取り、最後のバイトのみを読み取ると、同じエラーが発生します。スタック トレースとコードは次のとおりです。どんな助けでも大歓迎です。


スタックトレース:

    at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
   at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at ReportExprHostImpl.CustomCodeProxy.Decrypt(String ciphertext)

コード:

public function Decrypt(byval ciphertext as string) as string
  dim message as string
  dim key as string
  dim saltSize as integer
  saltsize = 32
  key = "KEYGOESHERE"

  dim allTheBytes as byte()
  allTheBytes = Convert.FromBase64String(ciphertext)

  dim saltBytes as byte()
  saltBytes = new byte(saltsize) {}

  dim ciphertextBytes as byte()
  ciphertextBytes = new byte(allTheBytes.Length - saltSize) {}

  dim i as integer
  for i = 0 to saltsize - 1
    saltBytes(i) = allTheBytes(i)
  next i

  for i = saltSize to (allTheBytes.Length - 1)
    ciphertextBytes(i - saltSize) = allTheBytes(i)
  next i

  try
    using keyDerivationFunction as System.Security.Cryptography.Rfc2898DeriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(key, saltBytes)
      dim keyBytes as byte()
      keyBytes = keyDerivationFunction.GetBytes(32)
      dim ivBytes as byte()
      ivBytes = keyDerivationFunction.GetBytes(16)

      using aesManaged as System.Security.Cryptography.AesManaged = new System.Security.Cryptography.AesManaged()
        aesManaged.Padding = System.Security.Cryptography.PaddingMode.PKCS7
        aesManaged.Mode = System.Security.Cryptography.CipherMode.CBC

        using decryptor as System.Security.Cryptography.ICryptoTransform = aesManaged.CreateDecryptor(keyBytes, ivBytes)
          using memoryStream as System.IO.MemoryStream = new System.IO.MemoryStream(ciphertextBytes)
            using cryptoStream as System.Security.Cryptography.CryptoStream = new System.Security.Cryptography.CryptoStream(memoryStream, decryptor, System.Security.Cryptography.CryptoStreamMode.Read)
              using streamReader as System.IO.StreamReader = new System.IO.StreamReader(cryptoStream)
                message = streamReader.ReadToEnd()
                return message
              end using
            end using
          end using
        end using
      end using
    end using
  catch e as Exception
    return e.StackTrace
  end try
end function
4

1 に答える 1

1

これはパディング エラーのように聞こえます。まず、CBC モードの AES では、復号化に正確なメッセージ サイズ (ブロックサイズ (16 バイト) の N 倍) が必要です。メッセージがこのサイズの場合、AES CBC 暗号文は常に復号化されます。他の問題は、実際にはパディングにのみ関連する可能性があります。そのため、最後に解読されたプレーン テキストに正しいパディングがなく、例外が発生します。

ここからは楽しい部分です。このエラーは次の場合に発生します。

  • バイナリ AES キーは同一ではありません。
  • アルゴリズムまたはモードが正しくない場合、または間違ったパディング アルゴリズムが使用されている場合。
  • 最後の 2 つのブロックのいずれかが破損している場合。
  • 暗号化の最後の部分が動作していない場合。

つまり、何か問題がある場合、パディング バイトの削除中に問題が発生する可能性があります。運が悪ければ、最後の不正なブロックは0116 進数のバイト値で終了し、パディングは成功し、パディングが整合性保護の代わりにならないことが示されます。

于 2012-09-28T21:44:57.007 に答える