CRYPTPROTECT_PROMPTSTRUCT Parameter error

D

DazedAndConfused

I converted a C# example of using dll crypt32 to VB .NET. The converted
example fails when Encypting/Decypting. I found that if instead of defining
a variable as and setting the values for CRYPTPROTECT_PROMPTSTRUCT; I
defined the variable as IntPtr and then set it to zero
CryptProtectData/CryptUnrotectData return without error.

The values between the C# and VB for CRYPTPROTECT_PROMPTSTRUCT are exact
except for szPrompt C# passes null and VB passes nothing, but in both cases
that is valid.

I did come accross a good example of Encrypting/Decrypting in VB .NET that I
can use and the values being passed for CRYPTPROTECT_PROMPTSTRUCT are
axactly the same as the code I am having the problem with.

This is driving me nuts!! I know I am missing something, somewhere, but I
just can not find the problem.


In anybody can figure this out and tell me where I went wrong that would be
great.


DataProtect Class
___________________________________________________
Imports System
Imports System.Text
Imports System.Runtime.InteropServices

Public Class DataProtect

<DllImport("crypt32", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function CryptProtectData( _
ByRef pDataIn As DATA_BLOB, _
ByVal szDataDescr As String, _
ByRef pOptionalEntropy As DATA_BLOB, _
ByVal pvReserved As IntPtr, _
ByVal pPromptStruct As CRYPTPROTECT_PROMPTSTRUCT, _
ByVal dwFlags As Integer, _
ByRef pDataOut As DATA_BLOB) As Boolean
End Function

<DllImport("crypt32", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function CryptUnprotectData(ByRef _
pDataIn As DATA_BLOB, _
ByVal szDataDescr As String, _
ByRef pOptionalEntropy As DATA_BLOB, _
ByVal pvReserved As IntPtr, _
ByVal pPromptStruct As CRYPTPROTECT_PROMPTSTRUCT, _
ByVal dwFlags As Integer, _
ByRef pDataOut As DATA_BLOB) As Boolean
End Function

<DllImport("kernel32")> _
Public Shared Function FormatMessage( _
ByVal dwFlags As Integer, _
ByRef lpSource As IntPtr, _
ByVal dwMessageId As Integer, _
ByVal dwLanguageId As Integer, _
ByRef lpBuffer As String, _
ByVal nsize As Integer, _
ByVal Arguments As IntPtr) As Integer

End Function

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure DATA_BLOB
Public cbData As Integer
Public pbData As IntPtr
End Structure

' Prompt structure to be used for required parameters.
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure CRYPTPROTECT_PROMPTSTRUCT
Public cbSize As Integer
Public dwPromptFlags As Integer
Public hwndApp As IntPtr
Public szPrompt As String
End Structure

Private Shared NullPtr As IntPtr = Nothing
Public Const CRYPTPROTECT_UI_FORBIDDEN As Integer = &H1
Public Const CRYPTPROTECT_LOCAL_MACHINE As Integer = &H4

' <summary>
' Initializes empty prompt structure.
' </summary>
' <param name="ps">
' Prompt parameter (which we do not actually need).
' </param>
Private Shared Sub InitPromptStruct _
( _
ByRef ps As CRYPTPROTECT_PROMPTSTRUCT _
)
ps.cbSize = Marshal.SizeOf(GetType(CRYPTPROTECT_PROMPTSTRUCT))
ps.dwPromptFlags = 0
ps.hwndApp = IntPtr.Zero
ps.szPrompt = Nothing
End Sub

Public Enum Store
USE_MACHINE_STORE
USE_USER_STORE
End Enum

Private myStore As Store
Public Sub New(ByVal tempStore As Store)
myStore = tempStore

End Sub

Public Function Encrypt(ByVal plainText As Byte(), _
ByVal optionalEntropy As Byte()) As Byte()
Dim retVal As Boolean = False
Dim plainTextBlob As DATA_BLOB = New DATA_BLOB
Dim cipherTextBlob As DATA_BLOB = New DATA_BLOB
Dim entropyBlob As DATA_BLOB = New DATA_BLOB
Dim prompt As CRYPTPROTECT_PROMPTSTRUCT = New CRYPTPROTECT_PROMPTSTRUCT
Dim dwFlags As Integer
InitPromptStruct(prompt)
Try
Try
Dim bytesSize As Integer = plainText.Length
plainTextBlob.pbData = Marshal.AllocHGlobal(bytesSize)
If plainTextBlob.pbData.Equals(Nothing) Then
Throw New Exception("Unable to allocate plaintext buffer.")
End If
plainTextBlob.cbData = bytesSize
Marshal.Copy(plainText, 0, plainTextBlob.pbData, bytesSize)
Catch ex As Exception
Throw New Exception("Exception marshalling data. " + ex.Message)
End Try
If Store.USE_MACHINE_STORE = myStore Then
dwFlags = CRYPTPROTECT_LOCAL_MACHINE Or CRYPTPROTECT_UI_FORBIDDEN
If Nothing Is optionalEntropy Then
'Allocate something
optionalEntropy = New Byte() {}
End If

Try
Dim bytesSize As Integer = optionalEntropy.Length
entropyBlob.pbData = Marshal.AllocHGlobal(optionalEntropy.Length)
If entropyBlob.Equals(Nothing) Then
Throw New Exception("Unable to allocate entropy data buffer.")
End If
Marshal.Copy(optionalEntropy, 0, entropyBlob.pbData, bytesSize)
entropyBlob.cbData = bytesSize
Catch ex As Exception
Throw New Exception("Exception entropy marshalling data. " +
ex.Message)
End Try
Else
dwFlags = CRYPTPROTECT_UI_FORBIDDEN
End If
retVal = CryptProtectData(plainTextBlob, "", entropyBlob, IntPtr.Zero,
prompt, dwFlags, cipherTextBlob)
If retVal = False Then
Throw New Exception("Encryption failed. " +
GetErrorMessage(Marshal.GetLastWin32Error()))
End If
If Not IntPtr.Zero.Equals(plainTextBlob.pbData) Then
Marshal.FreeHGlobal(plainTextBlob.pbData)
End If
If Not IntPtr.Zero.Equals(entropyBlob.pbData) Then
Marshal.FreeHGlobal(entropyBlob.pbData)
End If
Catch ex As Exception
Throw New Exception("Exception encrypting. " + ex.Message)
End Try
Dim cipherText(cipherTextBlob.cbData) As Byte
Marshal.Copy(cipherTextBlob.pbData, cipherText, 0, cipherTextBlob.cbData)
Marshal.FreeHGlobal(cipherTextBlob.pbData)
Return cipherText

End Function
Public Function Decrypt(ByVal cipherText() As Byte, ByVal optionalEntropy()
As Byte) As Byte()
Dim retVal As Boolean = False
Dim plainTextBlob As New DATA_BLOB
Dim cipherBlob As New DATA_BLOB
Dim prompt As New CRYPTPROTECT_PROMPTSTRUCT
InitPromptStruct(prompt)

Try
Try
Dim cipherTextSize As Integer = cipherText.Length
cipherBlob.pbData = Marshal.AllocHGlobal(cipherTextSize)

If cipherBlob.pbData.Equals(Nothing) Then
Throw New Exception("Unable to allocate cipherText buffer.")
End If

cipherBlob.cbData = cipherTextSize
Marshal.Copy(cipherText, 0, cipherBlob.pbData, cipherBlob.cbData)
Catch ex As Exception
Throw New Exception("Exception marshalling data. " + ex.Message)
End Try

Dim entropyBlob As New DATA_BLOB
Dim dwFlags As Integer

If Store.USE_MACHINE_STORE = myStore Then
' Using the machine store, should be providing entropy.
dwFlags = CRYPTPROTECT_LOCAL_MACHINE Or CRYPTPROTECT_UI_FORBIDDEN

' Check to see if the entropy is null
If Nothing Is optionalEntropy Then
'Allocate something
optionalEntropy = New Byte() {}
End If

Try
Dim bytesSize As Integer = optionalEntropy.Length
entropyBlob.pbData = Marshal.AllocHGlobal(bytesSize)

If entropyBlob.pbData.Equals(Nothing) Then
Throw New Exception("Unable to allocate entropy buffer.")
End If

entropyBlob.cbData = bytesSize
Marshal.Copy(optionalEntropy, 0, entropyBlob.pbData, bytesSize)
Catch ex As Exception
Throw New Exception("Exception entropy marshalling data. " +
ex.Message)
End Try
Else
' Using the user store
dwFlags = CRYPTPROTECT_UI_FORBIDDEN
End If

retVal = CryptUnprotectData(cipherBlob, "", entropyBlob, IntPtr.Zero,
prompt, dwFlags, plainTextBlob)

If False = retVal Then
Throw New Exception("Decryption failed. " +
GetErrorMessage(Marshal.GetLastWin32Error()))
End If

' Free the blob and entropy.
If Not cipherBlob.pbData.Equals(IntPtr.Zero) Then
Marshal.FreeHGlobal(cipherBlob.pbData)
End If

If Not entropyBlob.pbData.Equals(IntPtr.Zero) Then
Marshal.FreeHGlobal(entropyBlob.pbData)
End If
Catch ex As Exception
Throw New Exception("Exception decrypting. " + ex.Message)
End Try

Dim plainText(plainTextBlob.cbData) As Byte
Marshal.Copy(plainTextBlob.pbData, plainText, 0, plainTextBlob.cbData)
Marshal.FreeHGlobal(plainTextBlob.pbData)
Return plainText
End Function 'Decrypt

Private Shared Function GetErrorMessage(ByVal errorCode As Integer) As
[String]
Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
Dim messageSize As Integer = 255
Dim lpMsgBuf As [String] = ""
Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or
FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS

Dim ptrlpSource As New IntPtr
Dim prtArguments As New IntPtr

Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0,
lpMsgBuf, messageSize, prtArguments)

If 0 = retVal Then
Throw New Exception("Failed to format message for error code " +
CStr(errorCode) + ". ")
End If
Return lpMsgBuf
End Function 'GetErrorMessage

End Class

________________________________________________
test form
________________________________________

Imports System.text
Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents txtDataToEncrypt As System.Windows.Forms.TextBox
Friend WithEvents lblError As System.Windows.Forms.Label
Friend WithEvents btnEncypt As System.Windows.Forms.Button
Friend WithEvents txtEncryptedData As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.txtDataToEncrypt = New System.Windows.Forms.TextBox
Me.txtEncryptedData = New System.Windows.Forms.TextBox
Me.lblError = New System.Windows.Forms.Label
Me.btnEncypt = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'txtDataToEncrypt
'
Me.txtDataToEncrypt.Location = New System.Drawing.Point(16, 24)
Me.txtDataToEncrypt.Multiline = True
Me.txtDataToEncrypt.Name = "txtDataToEncrypt"
Me.txtDataToEncrypt.Size = New System.Drawing.Size(352, 20)
Me.txtDataToEncrypt.TabIndex = 0
Me.txtDataToEncrypt.Text = ""
'
'txtEncryptedData
'
Me.txtEncryptedData.Location = New System.Drawing.Point(16, 112)
Me.txtEncryptedData.Multiline = True
Me.txtEncryptedData.Name = "txtEncryptedData"
Me.txtEncryptedData.Size = New System.Drawing.Size(352, 20)
Me.txtEncryptedData.TabIndex = 1
Me.txtEncryptedData.Text = ""
'
'lblError
'
Me.lblError.AutoSize = True
Me.lblError.Location = New System.Drawing.Point(16, 192)
Me.lblError.Name = "lblError"
Me.lblError.Size = New System.Drawing.Size(0, 16)
Me.lblError.TabIndex = 2
'
'btnEncypt
'
Me.btnEncypt.Location = New System.Drawing.Point(16, 64)
Me.btnEncypt.Name = "btnEncypt"
Me.btnEncypt.TabIndex = 3
Me.btnEncypt.Text = "Encrypt"
'
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(544, 266)
Me.Controls.Add(Me.btnEncrypt3)
Me.Controls.Add(Me.btnEncypt2)
Me.Controls.Add(Me.btnEncypt)
Me.Controls.Add(Me.lblError)
Me.Controls.Add(Me.txtEncryptedData)
Me.Controls.Add(Me.txtDataToEncrypt)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub btnEncypt_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnEncypt.Click
Dim dp As New DataProtect(DataProtect.Store.USE_MACHINE_STORE)

Try
Dim entropy As Byte() = Nothing
Dim dataToEncrypt As Byte() =
Encoding.UTF8.GetBytes(txtDataToEncrypt.Text)
txtEncryptedData.Text = Convert.ToBase64String(dp.Encrypt(dataToEncrypt,
entropy))
Catch ex As Exception
lblError.ForeColor = System.Drawing.Color.Red
lblError.Text = "Exception." & Chr(13) & ex.Message
Return
End Try
lblError.Text = ""
End Sub


End Class
 
D

Dragon

Hello,

Change pPromptStruct parameter to ByRef in CryptProtectData &
CryptUnprotectData.

HTH,
Roman
 
D

DazedAndConfused

THANK YOU!!!!! Do you know where I can find a Dunce cap the size of a
tent??? :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top