これは、この質問のフォローアップです。
結果のデータを共有するレガシー製品との互換性を確保するために、VB.net から WinAPI 暗号化関数を呼び出しています。
コードは何年も正常に機能していましたが、最近、Windows Server 2012 で実行しているときに問題が発生しました。さまざまな例と以前の質問への回答を確認した後、以前は文字列だったものを変更するなど、コードをオーバーホールしました。より正しい機能であると私は信じています。以前は文字列でどのように機能していたのかわかりませんが、元の Server 2012 の問題を修正した後、文字列の NTE_BAD_LENGTH が原因で失敗していました。
ここで、文字列をバイト配列に変換した後、コードは以前と同じ方法で暗号化していないように見えます。また、CryptEncrypt によって生成されたものを復号化することもありません。
コードの大部分は次のとおりです。
(CryptCreateHash、CryptHashData、CryptDeriveKey の呼び出しがこれに先行します)
Dim _encoding As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding()
Dim data As String = "Testing123" ''define test String
Debug.WriteLine("Test Data: " & data)
''convert data to Byte()
Dim _bigBuffer As Byte() = New Byte(127) {} ''Buffer to be encrypted
Dim _dataBuffer As Byte() = _encoding.GetBytes(data) ''Get the text to be encrypted into a byte()
Buffer.BlockCopy(_dataBuffer, 0, _bigBuffer, 0, _dataBuffer.Length) ''Copy the data into the big buffer
Dim _dataBufferLength As UInteger = Convert.ToUInt32(_dataBuffer.Length) ''Get the length
Debug.Write("PlainText Data in buffer: ")
For Each _b As Byte In _dataBuffer
Debug.Write(_b & ", ")
Next
''Encrypt data.
If CryptoApi.CryptEncrypt(_hKey, IntPtr.Zero, True, 0, _bigBuffer, _dataBufferLength, _bigBuffer.Length) = False Then
Dim _error As Integer = Err.LastDllError
Throw New Exception("Error during CryptEncrypt. Error Code: " & _error.ToString)
End If
''print out the encrypted string
Dim _encryptedDataBuffer As Byte() = New Byte(_dataBufferLength - 1) {} ''Buffer, size is size of the output encrypted string
Buffer.BlockCopy(_bigBuffer, 0, _encryptedDataBuffer, 0, _dataBufferLength) ''copy from output buffer to new buffer
Dim _encryptedStringFromBuffer As String = _encoding.GetString(_encryptedDataBuffer) ''Decode buffer back to string
Debug.WriteLine("")
Debug.WriteLine("Encrypted: " & _encryptedStringFromBuffer) ''Write encrypted string from buffer
Debug.Write("Encrypted Data in buffer: ")
For Each _b As Byte In _encryptedDataBuffer
Debug.Write(_b & ", ")
Next
''Copy encrypted strings buffer, ready to decrypted
Dim _encryptedBufferCopy As Byte() = New Byte(127) {} ''new buffer to hold encrypted data
Buffer.BlockCopy(_bigBuffer, 0, _encryptedBufferCopy, 0, _bigBuffer.Length) ''copy the output of encryption
Dim _inputLengthCopy As UInteger = _dataBufferLength ''Copy the length of encrypted data
''Decrypt data.
If CryptoApi.CryptDecrypt(_hKey, IntPtr.Zero, True, 0, _encryptedBufferCopy, _encryptedBufferCopy.Length) = False Then
Dim _error As Integer = Err.LastDllError
Throw New Exception("Error during CryptDecrypt. Error Code: " & _error.ToString)
End If
Dim _outBuffer As Byte() = New Byte(_dataBufferLength - 1) {}
Buffer.BlockCopy(_bigBuffer, 0, _outBuffer, 0, _dataBufferLength)
Dim _stringFromBuffer As String = _encoding.GetString(_outBuffer)
Debug.WriteLine("")
Debug.Write("Decrypted Data in buffer: ")
For Each _b As Byte In _outBuffer
Debug.Write(_b & ", ")
Next
Debug.WriteLine("")
Debug.WriteLine("Decrypted: " & _stringFromBuffer)
私のメソッド プロトタイプは次のように定義されています。
Friend Declare Function CryptEncrypt Lib "advapi32.dll" _
(ByVal hKey As IntPtr, _
ByVal hHash As IntPtr, _
<MarshalAs(UnmanagedType.Bool)> ByVal final As Boolean, _
ByVal dwFlags As Integer, _
ByVal data As Byte(), _
ByRef pdwDataLen As Integer, _
ByVal dwBufLen As Integer) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
Friend Declare Function CryptDecrypt Lib "advapi32.dll" _
(ByVal hKey As IntPtr, _
ByVal hHash As IntPtr, _
<MarshalAs(UnmanagedType.Bool)> ByVal final As Boolean, _
ByVal dwFlags As Integer, _
ByVal data As Byte(), _
ByRef pdwDataLen As Integer) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
出力例は次のとおりです。
テスト データ: Testing123
バッファ内の平文データ: 84、101、115、116、105、110、103、49、50、51、
暗号化: CW?? ???_
バッファ内の暗号化データ: 12, 67, 87, 133, 158, 9, 139, 250, 255, 95,
バッファ内の復号化データ: 12, 67, 87, 133, 158, 9, 139, 250, 255、95、
解読済み: CW?? ???_
ご覧のとおり、復号化後のバッファはまったく同じままです。
なぜこれが起こっているのかわかりません。私の唯一の理論は、Byte() をエンコードしている文字セットに関係しているということですが、いくつか試してみましたが、違いはありません。これは、パスワード パラメータ ( に渡される Byte() ) にも適用される場合がありますCryptHashData。
どんな助けでも大歓迎です。
編集 1: 助けてくれてありがとう、私は今日早くバッファ コピーの問題に気付きました。
実際、VB の配列は最高のインデックスでインスタンス化されるため、127 は長さ 128 の配列を作成し、混乱を招きます。
あなたが話しているように、私の問題は現在エンコーディングにあると思います。以前は、現在行っているように、最初に byte() に変換されるのではなく、.NET String としてデータがCryptEncrypt/に渡されていました。CryptDecryptただし、アンマネージ コードがこの文字列をどのように処理したかはわかりません。おそらく、デフォルトの .NET エンコーディングまたは Windows エンコーディングですか?
UTF8 と Unicode を試しましたが、どちらも元のコードの動作をミラーリングせず、以前に保存された文字列を元の値に暗号化/復号化します。これは、従来の動作を正確に反映するために、アンマネージド メソッドを引き続き使用したい理由でもあります (アンマネージド メソッドを使用する VB6 アプリは、暗号化されたデータを .NET で復号化する前に生成するために使用されます)。
My Code は暗号化と復号化を行うようになりましたが、前述したように、同じ暗号化技術を使用しているにもかかわらず、出力される値は元のデータと一致しません。いつもお世話になっております。