title: Bouncy Castle OpenPGP with VB.Net
body: <p>I'm mainly posting this for anyone else that needs it since there seems to be a great lack of resources on the internet for this.  The samples I did find seemed hobbled together at best and never worked for me.  If you see or find anything wrong with this class, I'd love to know.  Note that this class is slightly modified for my particular implementation but should work fine against version 1.7 of the Bouncy Castle .Net source code.</p>
  
  <pre><code>Imports System.IO
  Imports Org.BouncyCastle.Bcpg.OpenPgp
  
  Public Class PgpDecrypt
      Private _mPublicKeyPath As String = "C:\MyPgpKeys\MyKey - Public.asc"
      Private _mPrivateKeyPath As String = "C:\MyPgpKeys\MyKey - Private.asc"
      Private _mPassPhrase As String = "&lt;passwoid&gt;"
  
      Public Function Decrypt(ByVal srcPath As String, ByVal dstPath As String) As Boolean
          Dim stEnc As Stream = PgpUtilities.GetDecoderStream(File.OpenRead(srcPath))
          Dim pof As New PgpObjectFactory(stEnc)
          Dim pked As PgpPublicKeyEncryptedData = Nothing
  
          Dim keyPrivate As PgpPrivateKey = Nothing
          For Each pked In GetEncryptedDataList(pof).GetEncryptedDataObjects
              keyPrivate = ReadPrivateKey(pked.KeyId)
              If Not keyPrivate Is Nothing Then Exit For
          Next
          If keyPrivate Is Nothing Then Return False
  
          Dim stDec As Stream = pked.GetDataStream(keyPrivate)
          pof = New PgpObjectFactory(stDec)
          Dim o As PgpObject = pof.NextPgpObject
          If TypeOf o Is PgpCompressedData Then
              pof = New PgpObjectFactory(DirectCast(o, PgpCompressedData).GetDataStream)
              o = pof.NextPgpObject
          End If
          While Not TypeOf o Is PgpLiteralData
              o = pof.NextPgpObject
              If o Is Nothing Then Return False
          End While
          Dim ld As PgpLiteralData = DirectCast(o, PgpLiteralData)
          Dim stOut As Stream = File.Create(dstPath)
          Dim stUnc As Stream = ld.GetInputStream
          Org.BouncyCastle.OpenPgp.Utilities.IO.Streams.PipeAll(stUnc, stOut)
          stOut.Close()
  
          Return True
      End Function
  
      Private Function GetEncryptedDataList(ByVal pof As PgpObjectFactory) As PgpEncryptedDataList
          Dim o As PgpObject = Nothing
          While Not TypeOf o Is PgpEncryptedDataList
              o = pof.NextPgpObject
              If o Is Nothing Then Return Nothing
          End While
          Return DirectCast(o, PgpEncryptedDataList)
      End Function
  
      Private Function ReadPublicKey(Optional ByVal useEmbedded As Boolean = False) As PgpPublicKey
          If useEmbedded Then
              Using st As Stream = Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(GetAssemblyName() &amp; ".MyKey - Public.asc")
                  Dim bundle As PgpSecretKeyRingBundle = New PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  For Each ring As PgpPublicKeyRing In bundle.GetKeyRings
                      For Each key As PgpPublicKey In ring.GetPublicKeys
                          If key.IsEncryptionKey Then Return key
                      Next
                  Next
              End Using
          Else
              Using st As Stream = File.OpenRead(_mPublicKeyPath)
                  Dim bundle As PgpPublicKeyRingBundle = New PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  For Each ring As PgpPublicKeyRing In bundle.GetKeyRings
                      For Each key As PgpPublicKey In ring.GetPublicKeys
                          If key.IsEncryptionKey Then Return key
                      Next
                  Next
              End Using
          End If
  
          Return Nothing
      End Function
  
      Private Function ReadSecretKey(Optional ByVal useEmbedded As Boolean = False) As PgpSecretKey
          If useEmbedded Then
              Using st As Stream = Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(GetAssemblyName() &amp; ".MyKey - Private.asc")
                  Dim bundle As PgpSecretKeyRingBundle = New PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  For Each ring As PgpSecretKeyRing In bundle.GetKeyRings
                      For Each key As PgpSecretKey In ring.GetSecretKeys
                          If key.IsSigningKey Then Return key
                      Next
                  Next
              End Using
          Else
              Using st As Stream = File.OpenRead(_mPrivateKeyPath)
                  Dim bundle As PgpSecretKeyRingBundle = New PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  For Each ring As PgpSecretKeyRing In bundle.GetKeyRings
                      For Each key As PgpSecretKey In ring.GetSecretKeys
                          If key.IsSigningKey Then Return key
                      Next
                  Next
              End Using
          End If
  
          Return Nothing
      End Function
  
      Private Function ReadPrivateKey(ByVal keyId As Long, Optional ByVal useEmbedded As Boolean = False) As PgpPrivateKey
          If useEmbedded Then
              Using st As Stream = Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(GetAssemblyName() &amp; ".MyKey - Private.asc")
                  Dim bundle As PgpSecretKeyRingBundle = New PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  Dim key As PgpSecretKey = bundle.GetSecretKey(keyId)
                  If key Is Nothing Then Return Nothing
                  Return key.ExtractPrivateKey(_mPassPhrase)
              End Using
          Else
              Using st As Stream = File.OpenRead(_mPrivateKeyPath)
                  Dim bundle As PgpSecretKeyRingBundle = New PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(st))
                  Dim key As PgpSecretKey = bundle.GetSecretKey(keyId)
                  If key Is Nothing Then Return Nothing
                  Return key.ExtractPrivateKey(_mPassPhrase)
              End Using
          End If
      End Function
  
      Private Function GetAssemblyName() As String
          Dim names() As String = Reflection.Assembly.GetExecutingAssembly.GetManifestResourceNames
          If names.Length &gt; 0 Then
              Return names(0).Split(".").First
          Else
              Return String.Empty
          End If
      End Function
  End Class
  </code></pre>