0

I have developed a function to sign a PDF created in memorystream and write it to a PDF. Now I'm looking to expand the function and instead of creating a PDF that is signed physically, I want to create the signed PDF in memory, so I can attach it to an email.

This is what I have:

    Using myPdfReader As New PdfReader(sourcePDFStream)
        Using myFileStream As New MemoryStream()
            Using myPdfStamper As PdfStamper = PdfStamper.CreateSignature(myPdfReader, myFileStream, "0"c)

                Dim myPdfSignatureAppearance As PdfSignatureAppearance = myPdfStamper.SignatureAppearance
                myPdfSignatureAppearance.SetVisibleSignature(New iTextSharp.text.Rectangle(100, 100, 250, 150), myPdfReader.NumberOfPages, "Digital Signature")

                Dim myExternalSignature As IExternalSignature = New PrivateKeySignature(pk, "SHA-256")
                MakeSignature.SignDetached(myPdfSignatureAppearance, myExternalSignature, chain, Nothing, Nothing, Nothing, 0, CryptoStandard.CMS)

                clsMail.SendHTMLMailPackStream("niels@email.be", "EFFFFactuurFEB", "NL", "docname", myVars, myFileStream)
            End Using
        End Using
    End Using

The problem I'm facing is that when I'm calling my 'SendHTMLMailPackStream' method, 'myfilestream' is already closed.

Does anyone knows an answer to this?

EDIT:

I found that everytime the MakeSignature.SignDetached() method is hit, it closes all my streams. But I have no idea how to cancel that..

Niels
  • 416
  • 5
  • 22

2 Answers2

0

I checked the writer class that is at play when you create signatures. This class is called PdfSignatureAppearance. Its Close() method indeed doesn't allow you to keep the original stream open. There's probably a reason for that. You don't want to jeopardize your signed PDF by adding extra bytes.

Looking at your code, I don't understand why it's necessary to keep that MemoryStream open.

Have you written the SendHTMLMailPackStream method yourself? I don't know what the parameters are supposed to be, but it's very awkward that it would accept a MemoryStream that already contains a full PDF (and nothing but a full PDF). One would expect that it either expects a byte[] that can be added as Multi-Part data, or a MemoryStream to which a mail message and Multi-Part data is written.

I don't see any use case where you'd pass a MemoryStream containing a PDF. Which bytes would you add after the %%EOF of that PDF?

Are you sure you're doing it right? By the way: Olivier mailed me, and I proposed that he gets in touch with iText Software in case the problem remains unresolved.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • the only this the stream will be used for is creating an attachment to an email: Dim att As New Attachment(stream, "filename.pdf") – Niels Apr 18 '16 at 06:42
  • I'm not a .NET developer, but if .NET is similar to Java (which it is), I assume that `stream` should be an `InputStream`, not an `OutputStream`. Why don't you create an `InputStream` using the `byte[]` stored in the `MemoryStream`? – Bruno Lowagie Apr 18 '16 at 07:00
  • As far as I know, I need to hit the MakeSignature.SignDetached() method first, otherwise it doens't matter what's in the stream/byte[], the PDF won't be signed. The purpose is to have an PDF that is signed but not saved on disk, and send it immediately via mail. – Niels Apr 19 '16 at 06:06
  • 1
    Yes, `SignDetached()` needs to be called. This will result in a `byte[]` containing all the bytes of a properly signed PDF. This `byte[]` isn't stored on disk. It is kept in a `MemoryStream`. This `MemoryStream` is closed because we don't want anyone to accidentally add bytes to a complete PDF. The `byte[]` starts with the bytes `%PDF-` and ends with `%%EOF`. Obviously, you can take that `byte[]` and embed it into a mail, but it doesn't make sense to add bytes after the `%%EOF` when the `byte[]` starts with `%PDF`. I count on your common sense to understand this. – Bruno Lowagie Apr 19 '16 at 06:33
  • I found the solution. Problem was I didn't know you could create an byte[] from an closed MemoryStream.. It's my first time working with memorystreams. Thank you for you answers and time ! – Niels Apr 19 '16 at 07:33
  • OK. That's great news :D – Bruno Lowagie Apr 19 '16 at 08:06
0

I needed to create an Byte[] from the closed MemoryStream.

With that Byte[] I was able to create an new MemoryStream to create the signed PDF:

Dim myExternalSignature As IExternalSignature = New PrivateKeySignature(pk, "SHA-256")
MakeSignature.SignDetached(myPdfSignatureAppearance, myExternalSignature, chain, Nothing, Nothing, Nothing, 0, CryptoStandard.CMS)

byteArray = myFileStream.ToArray()

Outside using:

Dim EndFileStream As New MemoryStream(byteArray)
clsMail.SendHTMLMailPackStream("niels@email.be", "EFFFFactuurFEB", "NL", "docname", myVars, EndFileStream)
Niels
  • 416
  • 5
  • 22