By default, BizTalk ships
with no encryption/decryption component. Many organizations need to
encrypt the message data as it is sent from BizTalk and decrypt is as
well once it is received. A fairly standard way to do this is to use PGP
(Pretty Good Privacy). Various vendors sell PGP packages; however,
nothing really exists to integrate PGP with BizTalk. The following
examples show you a potential implementation for this both on the send
side and the receive side.
There is an IMPORTS statement in the
beginning of the PGPEncodeComponent. This is the wrapper class that
supports the interaction with the GNU Privacy Guard API. The code for
this wrapper class is available for download fromwww.apress.com
should you want a full implementation; it is not included in this
example due to space constraints. Also, this wrapper class is the
logical point where you would implement your own PGP library wrapper
should you not want to use the GNU Privacy Guard implementation of the
PGP standard.
PGP Encode Component
The solution for implementing PGP within BizTalk
comprises two components, a send-side encoding component and a
receive-side decoding component. The following code shows the send-side
encoding component.
Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Collections
Imports System.Diagnostics
Imports System.Drawing
Imports System.IO
Imports System.Reflection
Imports Microsoft.BizTalk.Component.Interop
Imports ABC.BizTalk.PipelineComponents.PGPUtilities
Namespace ABC.BizTalk.PipelineComponents
<ComponentCategory(CategoryTypes.CATID_PipelineComponent),_
ComponentCategory(CategoryTypes.CATID_Encoder),_
System.Runtime.InteropServices.Guid("C1917FE1-841B-4583-A59E-B57F76871899")> _
Public Class PGPEncodeComponent
Implements IBaseComponent, Microsoft.BizTalk.Component.Interop.IComponent,_
Microsoft.BizTalk.Component.Interop.IPersistPropertyBag, IComponentUI
' Component information
#Region "IBaseComponent"
<Browsable(False)> _
Public ReadOnly Property Name() As String
Get
Return "PGP encoder"
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property Version() As String
Get
Return "1.0"
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property Description() As String
Get
Return "PGP Encode Pipeline Component"
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property Version() As String
Get
Return "1.0"
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property Description() As String
Get
Return "PGP Encode Pipeline Component"
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property Icon() As System.IntPtr
Get
Return (CType(resourceManager.GetObject("IconBitmap"),_
Bitmap)).GetHicon()
End Get
End Property
#End Region
Private resourceManager As System.Resources.ResourceManager = New_
System.Resources.ResourceManager("ABC.BizTalk.PipelineComponents",_
System.Reflection.Assembly.GetExecutingAssembly())
' Property: Recipient
Private _recipient As String
Public Property Recipient() As String
Get
Return _recipient
End Get
Set(ByVal value As String)
_recipient = value
End Set
End Property
Private _PGPBinDirectory As String
Public Property PGPBinDirectory() As String
Get
Return _PGPBinDirectory
End Get
Set(ByVal value As String)
_PGPBinDirectory = value
End Set
End Property
Private Function Encode(ByVal inStream As Stream) As Stream
Dim inFile As String = Path.GetTempFileName()
Dim outFile As String = Path.ChangeExtension(inFile, "gpg")
Try
DumpStreamToFile(inStream, inFile)
Dim GPG As GnuPGWrapper = New GnuPGWrapper(_PGPBinDirectory)
Dim GPGCommand As GnuPGCommand = GPG.Command
GPGCommand.Command = Commands.Encrypt
GPGCommand.Recipient = _recipient
GPGCommand.Armor = True
GPGCommand.InputFile = inFile
GPGCommand.OutputFile = outFile
GPG.Execute(Nothing)
outStream = ReadFileToMemoryStream(outFile)
Catch ex As Exception
System.Diagnostics.Debug.WriteLine(ex)
Throw ex
Finally
If File.Exists(inFile) Then
File.Delete(inFile)
End If
If File.Exists(outFile) Then
File.Delete(outFile)
End If
End Try
Return outStream
End Function
#Region "IPersistPropertyBag Members"
Public Sub InitNew()
End Sub
Public Sub GetClassID(<System.Runtime.InteropServices.Out()> ByRef _
classID As Guid)
classID = New Guid("A398E8D1-4213-4438-9010-66F366D4BDF4")
End Sub
Public Sub Load(ByVal propertyBag As IPropertyBag, ByVal errorLog _
As Integer)
Dim text As String
text = Convert.ToString(ReadPropertyBag(propertyBag, "Recipient"))
If Not text Is Nothing Then
_recipient = text
End If
text = Convert.ToString(ReadPropertyBag(propertyBag, "GnuPGBinDir"))
If Not text Is Nothing Then
_ PGPBinDirectory = text
End If
End Sub
Public Sub Save(ByVal propertyBag As IPropertyBag, ByVal clearDirty As_
Boolean, ByVal saveAllProperties As Boolean)
Dim val As Object
val = CObj(_recipient)
WritePropertyBag(propertyBag, "Recipient", val)
val = CObj(_PGPBinDirectory)
WritePropertyBag(propertyBag, "PGPBinDirectory", val)
End Sub
#End Region
#Region "IComponent Members"
Public Function Execute(ByVal pContext As IPipelineContext, ByVal pInMsg As_
Microsoft.BizTalk.Message.Interop.IBaseMessage) As_
Microsoft.BizTalk.Message.Interop.IBaseMessage
Try
If Not pInMsg Is Nothing Then
Dim originalStream As Stream = _
pInMsg.BodyPart.GetOriginalDataStream()
pInMsg.BodyPart.Data = Encode(originalStream)
pContext.ResourceTracker.AddResource(pInMsg.BodyPart.Data)
End If
Catch ex As Exception
System.Diagnostics.Debug.WriteLine("Exception caught in_
ABC.BizTalk.PipelineComponents.PGPEncodeComponent::Execute: " & ex.Message)
End Try
Return pInMsg
End Function
#End Region
#Region "IComponentUI Members"
' <summary>
'The Validate method is called by the BizTalk Editor during the build
'of a BizTalk project.
'</summary>
'<param name="obj">An Object containing the configuration
'properties.</param>
'<returns>The IEnumerator enables the caller to enumerate through a
'collection of strings containing error messages. These error messages
'appear as compiler error messages. To report successful property
'validation, the method should return an empty enumerator.</returns>
Public Function Validate(ByVal projectSystem As Object) As IEnumerator
' example implementation:
' ArrayList errorList = new ArrayList();
' errorList.Add("This is a compiler error");
' return errorList.GetEnumerator();
Return Nothing
End Function
#End Region
#Region "Utility Functions"
Public Shared Sub DumpStreamToFile(ByVal fromStream As Stream, ByVal _
toFilename As String)
Dim file As FileStream = Nothing
Try
file = New FileStream(toFilename, System.IO.FileMode.Create)
Dim tmpBuff As Byte() = New Byte(4095) {}
Dim bytesRead As Integer = 0
bytesRead = file.Read(tmpBuff, 0, tmpBuff.Length)
memStream.Write(tmpBuff, 0, bytesRead)
Do While bytesRead <> 0
bytesRead = fromStream.Read(tmpBuff, 0, tmpBuff.Length)
file.Write(tmpBuff, 0, bytesRead)
Loop
file.Close()
file = Nothing
Finally
If Not file Is Nothing Then
file.Close()
End If
End Try
End Sub
Public Shared Function ReadFileToMemoryStream(ByVal fromFilename As String)_
As MemoryStream
Dim file As FileStream = Nothing
Try
file = New FileStream(fromFilename, System.IO.FileMode.Open)
Dim memStream As MemoryStream = New MemoryStream()
Dim tmpBuff As Byte() = New Byte(4095) {}
bytesRead = file.Read(tmpBuff, 0, tmpBuff.Length)
memStream.Write(tmpBuff, 0, bytesRead)
Dim bytesRead As Integer = bytesRead = file.Read(tmpBuff, 0, _
tmpBuff.Length)
Do While bytesRead <> 0
memStream.Write(tmpBuff, 0, bytesRead)
bytesRead = file.Read(tmpBuff, 0, tmpBuff.Length)
Loop
file.Close()
file = Nothing
memStream.Position = 0
Return memStream
Finally
If Not file Is Nothing Then
file.Close()
End If
End Try
End Function
Public Shared Function ReadPropertyBag(ByVal pb As_
Microsoft.BizTalk.Component.Interop.IPropertyBag, ByVal propName As _
String) As Object
Dim val As Object = Nothing
Try
pb.Read(propName, val, 0)
Catch e1 As ArgumentException
Return val
Catch ex As Exception
Throw New ApplicationException(ex.Message)
End Try
Return val
End Function
''' <summary>
''' Writes property values into a property bag.
''' </summary>
''' <param name="pb">Property bag.</param>
''' <param name="propName">Name of property.</param>
''' <param name="val">Value of property.</param>
Public Shared Sub WritePropertyBag(ByVal pb As_
Microsoft.BizTalk.Component.Interop.IPropertyBag, ByVal propName As String, ByVal _
val As Object)
Try
pb.Write(propName, val)
Catch ex As Exception
Throw New ApplicationException(ex.Message)
End Try
End Sub
#End Region
End Class
End Namespace