VisualSignature.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' © MESCIUS inc. All rights reserved.
'' 
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.AcroForms
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
Imports System.Security.Cryptography.X509Certificates

'' このサンプルは、SignatureField と署名画像を使用して、PDF を作成し
'' .pfx ファイルで署名する方法を示します。
'' また、サンプルは署名されたファイルを別の GcPdfDocument インスタンスに読み込み、
'' 署名を検証します。
'' このサンプルは SignDoc サンプルと同じですが、署名を表す画像を追加します。
Public Class VisualSignature
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim page = doc.NewPage()
        Dim tf = New TextFormat() With {.Font = Util.getFont(), .FontSize = 14}
        page.Graphics.DrawString("デジタル署名のサンプルです" + vbLf +
            "このPDFは表示している印影画像に署名されています。",
            tf, New PointF(72, 72))
        page.Graphics.DrawString(
            $"注意:署名に使用している証明書、印影はテスト用です。{vbCrLf}ブラウザのビルトインビューワによっては署名が表示されない場合があります。",
            New TextFormat(tf) With {.FontSize = 10}, New PointF(72, 72 * 2))

        '' テスト証明書を初期化します。
        Dim pfxPath = Path.Combine("Resources", "Misc", "GcPdfTest.pfx")
        Dim cert = New X509Certificate2(File.ReadAllBytes(pfxPath), "qq",
                X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable)
        Dim sp = New SignatureProperties() With
        {
            .SignatureBuilder = New Pkcs7SignatureBuilder() With {
                .CertificateChain = New X509Certificate2() {cert}
            },
            .Location = "DioDocs for PDF サンプル",
            .SignerName = "株式会社ディオドック"
        }

        '' 署名を表す画像を追加します。
        sp.SignatureAppearance.Image = GCDRAW.Image.FromFile(Path.Combine("Resources", "ImagesBis", "kaku_in.png"))
        sp.SignatureAppearance.CaptionImageRelation = GrapeCity.Documents.Pdf.Annotations.CaptionImageRelation.ImageOnly

        '' 署名を保持する署名フィールドを初期化します。
        Dim sf = New SignatureField()
        sf.Widget.Rect = New RectangleF(72 * 2, 72 * 2.5F, 72 * 2, 72 * 2)
        sf.Widget.Page = page
        sf.Widget.BackColor = Color.LightSeaGreen
        sf.Widget.DefaultAppearance.Font = Util.getFont()
        sf.Widget.ButtonAppearance.Caption = $"Signer: {sp.SignerName}{vbCrLf}Location: {sp.Location}"
        '' 文書に署名フィールドを追加します。
        doc.AcroForm.Fields.Add(sf)
        '' 署名フィールドと署名プロパティを結びつけます。
        sp.SignatureField = sf

        '' 署名して文書を保存します。
        '' 注意:
        '' - 署名と保存は一連の操作であり、2つは分離できません。
        '' - Sign() メソッドに渡されたストリームは読み込み可能でなければなりません。
        doc.Sign(sp, stream)

        '' ストリームを巻き戻して、作成した文書を別の GcPdfDocument
        '' オブジェクトに読み込み、署名を確認します。
        stream.Seek(0, SeekOrigin.Begin)
        Dim doc2 = New GcPdfDocument()
        doc2.Load(stream)
        Dim sf2 = CType(doc2.AcroForm.Fields(0), SignatureField)
        If Not sf2.Value.VerifySignatureValue() Then
            Throw New Exception("署名の検証に失敗しました。")
        End If

        '' 終了(生成および署名された文書はすでに 'stream' に保存されています)。
        Return doc.Pages.Count
    End Function
End Class