1

我主要是为其他需要它的人发布这个,因为互联网上似乎非常缺乏这方面的资源。我确实找到的样本似乎充其量只是蹒跚而行,对我来说从来没有用过。如果你看到或发现这门课有什么问题,我很想知道。请注意,该类针对我的特定实现稍作修改,但在 Bouncy Castle .Net 源代码的 1.7 版中应该可以正常工作。

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 = "<passwoid>"

    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() & ".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() & ".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() & ".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 > 0 Then
            Return names(0).Split(".").First
        Else
            Return String.Empty
        End If
    End Function
End Class
4

1 回答 1

1

惊人的!非常感谢您发布这个 - 它几乎可以开箱即用。需要将其中一项更改Org.BouncyCastle.OpenPgp.Utilities.IO.Streams.PipeAll(stUnc, stOut)替换为Org.BouncyCastle.Utilities.IO.Streams.PipeAll(stUnc, stOut).

于 2013-04-23T15:02:23.217 回答