1

これは、この質問のフォローアップです。

結果のデータを共有するレガシー製品との互換性を確保するために、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 は暗号化と復号化を行うようになりましたが、前述したように、同じ暗号化技術を使用しているにもかかわらず、出力される値は元のデータと一致しません。いつもお世話になっております。

4

1 に答える 1