-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBouncyCastleSigner.vb
105 lines (88 loc) · 3.41 KB
/
BouncyCastleSigner.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Imports DevExpress.Pdf
Imports Org.BouncyCastle.Asn1
Imports Org.BouncyCastle.Asn1.X509
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Crypto.Digests
Imports Org.BouncyCastle.Crypto.Encodings
Imports Org.BouncyCastle.Crypto.Engines
Imports Org.BouncyCastle.Pkcs
Imports Org.BouncyCastle.Security
Imports DevExpress.Office.Tsp
Imports DevExpress.Office.DigitalSignatures
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Namespace CustomSigner
' Declare a custom class to calculate a digest value:
Public Class BouncyCastleDigestCalculator
Implements IDigestCalculator
Private ReadOnly digest As IDigest
Public ReadOnly Property AlgorithmOid As String Implements IDigestCalculator.AlgorithmOid
Get
Return DigestUtilities.GetObjectIdentifier(digest.AlgorithmName).Id
End Get
End Property
Public Sub New()
digest = New Sha512Digest()
End Sub
Public Function ComputeDigest(ByVal stream As Stream) As Byte() Implements IDigestCalculator.ComputeDigest
digest.Reset()
Dim buffer((1024 * 1024) - 1) As Byte
Dim readByteCount As Integer
Do
readByteCount = stream.Read(buffer, 0, buffer.Length)
If readByteCount <> 0 Then
digest.BlockUpdate(buffer, 0, readByteCount)
End If
Loop While readByteCount <> 0
Dim result(GetDigestSize() - 1) As Byte
digest.DoFinal(result, 0)
Return result
End Function
Public Function GetDigestSize() As Integer Implements IDigestCalculator.GetDigestSize
Return digest.GetDigestSize()
End Function
End Class
Public Class BouncyCastleSigner
Inherits Pkcs7SignerBase
'Specify the signing algoritm's OID:
Private Const PKCS1RsaEncryption As String = "1.2.840.113549.1.1.1"
Private ReadOnly certificates()() As Byte
Private ReadOnly rsaEngine As IAsymmetricBlockCipher
'Specify a custom digest calculator:
Protected Overrides ReadOnly Property DigestCalculator() As IDigestCalculator
Get
Return New BouncyCastleDigestCalculator()
End Get
End Property
Protected Overrides ReadOnly Property SigningAlgorithmOID As String
Get
Return PKCS1RsaEncryption
End Get
End Property
Public Sub New(ByVal file As String, ByVal password As String, ByVal tsaClient As ITsaClient)
MyBase.New(tsaClient, Nothing, Nothing, PdfSignatureProfile.Pdf)
'Read PKCS#12 file:
Dim pkcs As Pkcs12Store = New Pkcs12StoreBuilder().Build()
Dim fs As FileStream = System.IO.File.Open(file, FileMode.Open)
pkcs.Load(fs, password.ToCharArray())
'Get the certificate's alias:
Dim [alias] = pkcs.Aliases.OfType(Of String)().First(Function(a) pkcs.IsKeyEntry(a))
'Get the certificate's chain:
certificates = pkcs.GetCertificateChain([alias]).Select(Function(c) c.Certificate.GetEncoded()).ToArray()
'Initialize the encryption engine:
rsaEngine = New Pkcs1Encoding(New RsaBlindedEngine())
rsaEngine.Init(True, pkcs.GetKey([alias]).Key)
End Sub
Protected Overrides Function GetCertificates() As IEnumerable(Of Byte())
Return certificates
End Function
Protected Overrides Function SignDigest(ByVal digest() As Byte) As Byte()
'Create the digest info object
'Encrypted by the signer's private key:
Dim dInfo = New DigestInfo(New AlgorithmIdentifier(New DerObjectIdentifier(DigestCalculator.AlgorithmOid), DerNull.Instance), digest)
Dim digestInfo() As Byte = dInfo.GetEncoded()
Return rsaEngine.ProcessBlock(digestInfo, 0, digestInfo.Length)
End Function
End Class
End Namespace