Visible Signature in a PDF file - pdf

I 'm trying to create a visible signature in a PDF file.
Taking a simple PDF "hello world" file:
%PDF-1.7
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/MediaBox [ 0 0 200 200 ]
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/Font <<
/F1 4 0 R
>>
>>
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
endobj
5 0 obj % page content
<<
/Length 44
>>
stream
BT
10 05 TD
/F1 12 Tf
(Hello, world!) Tj
ET
endstream
endobj
xref
0 6
0000000000 65535 f
0000000010 00000 n
0000000079 00000 n
0000000173 00000 n
0000000301 00000 n
0000000380 00000 n
trailer
<<
/Size 6
/Root 1 0 R
>>
startxref
492
%%EOF
And signing it with a text to appear "Yolo" at some position at the first page produces this:
%PDF-1.7
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/MediaBox [ 0 0 200 200 ]
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/Font <<
/F1 4 0 R
>>
>>
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
endobj
5 0 obj % page content
<<
/Length 44
>>
stream
BT
10 05 TD
/F1 12 Tf
(Hello, world!) Tj
ET
endstream
endobj
xref
0 6
0000000000 65535 f
0000000010 00000 n
0000000079 00000 n
0000000173 00000 n
0000000301 00000 n
0000000380 00000 n
trailer
<<
/Size 6
/Root 1 0 R
>>
startxref
492
%%EOF
8 0 obj
<</F 132/Type/Annot/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/DR<<>>/T(Signature1)/V 6 0 R/P 3 0 R/AP<</N 7 0 R>>>>
endobj
6 0 obj
<</Contents <...>/Type/Sig/SubFilter/ETSI.CAdES.detached/M(D:20190626125540+00'00')/ByteRange [0 824 60826 1401]/Filter/Adobe.PPKLite>>
endobj
9 0 obj
<</BaseFont/Helvetica/Type/Font/Subtype/Type1/Encoding/WinAnsiEncoding/Name/Helv>>
endobj
10 0 obj
<</BaseFont/ZapfDingbats/Type/Font/Subtype/Type1/Name/ZaDb>>
endobj
12 0 obj
<</Length 35>>stream
BT
1 15 TD
/Helv 6 Tf
(Yolo) Tj
ET
endstream
endobj
7 0 obj
<</Type/XObject/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Subtype/Form/BBox[0 0 0 0]/Matrix [1 0 0 1 0 0]/Length 8/FormType 1/Filter/FlateDecode>>stream
xœ
endstream
endobj
3 0 obj
<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 4 0 R>>>>/Contents [12 0 R 5 0 R]/Annots[8 0 R]>>
endobj
2 0 obj
<</Type/Pages/MediaBox[0 0 200 200]/Count 1/Kids[3 0 R]>>
endobj
1 0 obj
<</AcroForm<</Fields[8 0 R]/DR<</Font<</Helv 9 0 R/ZaDb 10 0 R>>>>/DA(/Helv 0 Tf 0 g )/SigFlags 3>>/Type/Catalog/Pages 2 0 R>>
endobj
11 0 obj
<</Producer(AdES Tools https://www.turboirc.com)/ModDate(D:20190626125540+00'00')>>
endobj
xref
0 4
0000000000 65535 f
0000061604 00000 n
0000061529 00000 n
0000061414 00000 n
6 7
0000000804 00000 n
0000000000 65535 f
0000000679 00000 n
0000060952 00000 n
0000061050 00000 n
0000061746 00000 n
0000061127 00000 n
trailer
<</Root 1 0 R/Prev 492/Info 11 0 R/Size 17/ID[<4BB225C2F629BB21464F66FBF2FED264><8E3C9AD8354C66931EAAC282088455EA>]>>
startxref
61846
%%EOF
So there is an object in the PDF that shows some text in the first page:
12 0 obj
<</Length 35>>stream
BT
1 15 TD
/Helv 6 Tf
(Yolo) Tj
ET
endstream
endobj
My problem is now that this object is treated like a common text object in adobe reader. I want it, when clicked, to go to the digital signature, like how Adobe Acrobat signs the documents.
What do I miss? Is there a parameter in the digital signature (The 6 or 8 number object) or in any of the other objects my app puts in the new PDF that links the text object with the signature?
Thanks a lot.

Your object 8
8 0 obj
<</F 132/Type/Annot/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/DR<<>>/T(Signature1)/V 6 0 R/P 3 0 R/AP<</N 7 0 R>>>>
endobj
is an AcroForm form field for signatures (as the FT entry with value Sig tells us). At the same time, though, this object also is a form field widget annotation (as can be seen in the Type and Subtype entries). Form field widget annotations are the visual representations of form fields, and if a form field has only one representation, the widget can be merged with the form field as in your object.
In your case the annotation has a 0x0 size (/Rect[0 0 0 0]), i.e. invisible. To have a visible representation, you need an annotation rectangle that does not vanish.
The content that is displayed is defined in the normal appearance /AP<</N 7 0 R>> which points to object 7.
7 0 obj
<</Type/XObject/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Subtype/Form/BBox[0 0 0 0]/Matrix [1 0 0 1 0 0]/Length 8/FormType 1/Filter/FlateDecode>>stream
xœ
endstream
endobj
At first glance this looks pretty empty, even after decompression.
Thus, what you have to do is
choose a non-vanishing rectangle for your signature form field annotation,
adapt the BBox of the normal appearance stream to that annotation rectangle, and
create a non-empty content in the normal appearance stream of that annotation instead of adding page content.
Furthermore you should fix obvious errors in your PDF, e.g.
object 7, your signature field normal appearance, is marked as free in your cross references
your trailer claims a size of 17
For details please study the PDF specification ISO 32000. Part 1 is published for download by Adobe at https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf
In particular sections
12.5 "Annotations"
12.7 "Interactive Forms"
12.8 "Digital Signatures"

Related

PDF Unknown signing icon

I am signing PDF programmatically. Every new signature is added in an incremental way where I add the signature dictionnary after the %EOF and I update the AcroForm like this (sorry, I'm at work so I can't upload the PDF) :
... // ORIGINAL FILE
trailer
<<
/Size 11
/Root 1 0 R
/Info 10 0 R
>>
startxref
2714
%%EOF
1 0 obj
<</Type /Catalog /Outlines 2 0 R /Pages 3 0 R /AcroForm <</Fields [11 0 R ] /SigFlags 3 >> /Names 14 0 R >>
endobj
...
11 0 obj
<</Type /Annot /SubType /Widget /Rect [0 0 0 0 ] /P 4 0 R /F 4 /FT /Sig /T (Signature) /Ff 0 /V <</Type /Sig /Filter /Adobe.PPKLite /SubFilter /adbe.pkcs7.detached /ByteRange [0 3729 15473 422 ] /Contents <308209...>
/M (D:20170801165520+02'00') >> >>
endobj
...
trailer
<</Size 15 /Root 1 0 R /Info 10 0 R /Prev 2714 >>
startxref
15609
%%EOF
1 0 obj
<</Type /Catalog /Outlines 2 0 R /Pages 3 0 R /AcroForm <</Fields [15 0 R ] /SigFlags 3 >> /Names 14 0 R >>
endobj
...
15 0 obj
<</Type /Annot /SubType /Widget /Rect [0 0 0 0 ] /P 4 0 R /F 4 /FT /Sig /T (Signature) /Ff 0 /V <</Type /Sig /Filter /Adobe.PPKLite /SubFilter /adbe.pkcs7.detached /ByteRange [0 16632 28376 387 ] /Contents <3082062...>
/M (D:20170802094848+02'00') >> >>
endobj
16 0 obj
...
<</Size 18 /Root 1 0 R /Info 10 0 R /Prev 15609 >>
startxref
28476
%%EOF
Maybe the problem is that I have multiple objects having the same ID and that my last AcroForm only refers to the last signature ? I want to be able to sign one file multiple times but I have an issue. The first signing is okay and displays this banner :
And then I try to sign the same file another time with another certificate and this give me this trash can icon next to the signature and says it was removed as you can see here :
I am using Zend_PDF to parse the file and add the signature.
EDIT : Thanks to #mkl the 2 signatures are now recognized by Adobe Reader. My AcroForms now look like this :
2714
%%EOF
1 0 obj
<</Type /Catalog /Outlines 2 0 R /Pages 3 0 R /AcroForm <</Fields [11 0 R ] /SigFlags 3 >> /Names 14 0 R >>
endobj
...
15610
%%EOF
1 0 obj
<</Type /Catalog /Outlines 2 0 R /Pages 3 0 R /AcroForm <</Fields [11 0 R 15 0 R ] /SigFlags 3 >> /Names 14 0 R >>
endobj
...
And I have this surprising errors since I didn't modify anything about the ByteRange and I verified by hand that they are correct. Is is about my new modifications ?
While adding the first signature you set the AcroForm dictionary to
/AcroForm <</Fields [11 0 R ] /SigFlags 3 >>
For the second one, you set it to
/AcroForm <</Fields [15 0 R ] /SigFlags 3 >>
I.e. you removed 11 0 R from it and added 15 0 R to it. Thus, you indeed deleted the first signature field from the form structure.
You should instead only have added the new signature field:
/AcroForm <</Fields [11 0 R 15 0 R ] /SigFlags 3 >>
Furthermore, both your signature fields have the same name
11 0 obj
<<
...
/T (Signature)
...
>>
endobj
...
15 0 obj
<<
...
/T (Signature)
...
>>
endobj
Obviously, different form fields must have different names.

Manually creating interactive PDFs

For reasons tedious to explain, I need to create simple PDFs from a C# application without using any third-party libraries. The PDFs in question need to include text and line drawings, and if possible should include images, radio buttons, and text fields. I've been reading Adobe's documentation, which is for the most part straightforward, but so far have been unable to figure out how to make interactive fields actually appear on the document.
For example, consider the partial test PDF document described below:
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
/AcroForm 6 0 R
>>
endobj
...
6 0 obj
<< /Fields [ 7 0 R ]
/DR 5 0 R
>>
endobj
7 0 obj
<< /FT /Btn
/Ff 65536
/Kids [ 8 0 R 9 0 R ]
>>
endobj
8 0 obj
<< /Parent 7 0 R
/AS /FieldA
/AP 10 0 R
>>
endobj
9 0 obj
<< /Parent 8 0 R
/AS /FieldB
/AP 10 0 R
>>
endobj
10 0 obj
<< /N
<< /FieldA 11 0 R
/FieldB 12 0 R
/Off 13 0 R
>>
>>
endobj
11 0 obj
<< /Length 59 >>
stream
BT
/F1 12 Tf
0 0 Td
(Field A) Tj
ET
endstream
endobj
...
Where 5 0 R references a resource dictionary containing the font /F1 and 12 0 R and 13 0 R reference streams similar to 11 0 R with the string replaced by Field B and Off respectively.
What changes do I need to make to the document to cause the fields thus defined to actually appear on a page?
Edit: Since mkl asked, here's the whole pdf (extra line breaks removed to save space)
%PDF-1.7
%¥±ë
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 200 200] >> endobj
3 0 obj << /Type /Page /Parent 2 0 R /Resources 5 0 R /Contents 4 0 R >> endobj
4 0 obj << /Length 39 >>
stream
BT /F1 12 Tf 0 0 Td (Hello World) Tj ET
endstream
endobj
5 0 obj << /Font << /F1 << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> >> >> endobj
6 0 obj << /Fields [ 7 0 R ] /DR 5 0 R >> endobj
7 0 obj << /FT /Btn /Ff 65536 /Kids [ 8 0 R 9 0 R ] >> endobj
8 0 obj << /Parent 7 0 R /AS /FieldA /AP 10 0 R >> endobj
9 0 obj << /Parent 7 0 R /AS /FieldB /AP 10 0 R >> endobj
10 0 obj << /N << /FieldA 11 0 R /FieldB 12 0 R /Off 13 0 R >> >> endobj
11 0 obj << /Length 59 >>
stream
BT /F1 12 Tf 0 0 Td (Field A) Tj ET
endstream
endobj
12 0 obj << /Length 39 >>
stream
BT /F1 12 Tf 0 0 Td (Field B) Tj ET
endstream
endobj
13 0 obj << /Length 39 >>
stream
BT /F1 12 Tf 0 0 Td (Off... ) Tj ET 94
endstream
endobj
xref
0 14
0000000000 65535 f
0000000018 00000 n
0000000068 00000 n
0000000150 00000 n
0000000233 00000 n
0000000327 00000 n
0000000420 00000 n
0000000470 00000 n
0000000533 00000 n
0000000592 00000 n
0000000651 00000 n
0000000727 00000 n
0000000821 00000 n
0000000917 00000 n
trailer << /Root 1 0 R /Size 5 >>
startxref
1013
%%EOF
Based on the full file you posted I see several issues (there might be more):
The document catalog does not include an /AcroForm entry
The page does not include an /Annots entry with links to field widgets
Field definitions 8 and 9 are incomplete, they do not include the widget annotation entries. These entries specify the field location on the page
Your field is a pushbutton, it does not have different appearance states, the /N appearance should be a reference to an appearance stream (11, 12 or 13)
Field appearances 11, 12, 13 are invalid, entries such as /Type, /Subtype, /BBox, /Resources are missing
Update: below you can find a minimum file structure for a radio button.
1 0 obj
<< /Type /Catalog /Version /1.4 /Pages 8 0 R /AcroForm <</Fields [2 0 R ]>> >>
endobj
2 0 obj
<< /FT /Btn /T (Radio) /V /Off /Kids [5 0 R 3 0 R ] /Ff 32768 >>
endobj
3 0 obj
<< /Type /Annot /F 4 /Rect [250 667 270 687 ] /Subtype /Widget /AS /Off /AP << /N << /Two 7 0 R /Off 6 0 R >> >> /Parent 2 0 R /P 4 0 R >>
endobj
4 0 obj
<< /Type /Page /Contents null /MediaBox [0 0 612 792 ] /Parent 8 0 R /Annots [5 0 R 3 0 R ] >>
endobj
5 0 obj
<< /Type /Annot /F 4 /Rect [150 667 170 687 ] /Subtype /Widget /AS /Off /AP << /N << /One 7 0 R /Off 6 0 R >> >> /Parent 2 0 R /P 4 0 R >>
endobj
6 0 obj
<< /Type /XObject /Subtype /Form /BBox [0 0 20 20 ] /Length 74 >>
stream
/DeviceRGB CS 0 0 0 SC 1 w 0.5 0.5 m 19.5 0.5 l 19.5 19.5 l 0.5 19.5 l h S
endstream
endobj
7 0 obj
<< /Type /XObject /Subtype /Form /BBox [0 0 20 20 ] /Length 55 >>
stream
/DeviceRGB cs 0 0 0 sc 0 0 m 20 0 l 20 20 l 0 20 l h f
endstream
endobj
8 0 obj
<< /Type /Pages /Count 1 /Kids [4 0 R ] >>
endobj
You can download minimum radio button sample and a more detailed radio button sample.
Using our XFINIUM.PDF Inspector you can visualize the PDF file structure.
Your fields will need to include what are known as "appearances" which are XObjects that contain the drawing instructions used to create the visual appearance of the field. See section 12.5.5 of the PDF Specification. Alternatively, you can set the NeedAppearances property of the AcroForm entry in the document catalog to true. See section 12.7.2 of the PDF specification. Setting this to true will cause a conforming viewer to create the appearances of the fields based on their properties. However, you can't count on most viewers to do this.

Is it possible to append data to a PDF page with modifying the original page object

I'm trying to append some data to a page of a PDF, by using the PDF versioning system (e.g. appending data to the end of a valid PDF with it's own XREF and what not).
Right now I'm just attempting to do a proof of concept. I can append an orange square to an existing page, but it requires me to parse out the original page object, alter the Contents array, and add that the data I'm appending. Example:
Original Page:
5 0 obj
<<
/Parent 4 0 R
/Contents[2 0 R 8 0 R 3 0 R]
/Type
/Page
/Resources
<<
/ExtGState
<<
/GSa 6 0 R
>>
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/XObject
<<
/Im9 9 0 R
>>
/ColorSpace
<<
/CSp/DeviceRGB/CSpg/DeviceGray/PCSp 7 0 R
>>
/Font
<<
/F11 10 0 R
/F6 11 0 R
/Xi0 1 0 R
>>
>>
/MediaBox[0 0 595 842]
/Annots 12 0 R
>>
endobj
Modified page:
5 0 obj
<<
/Parent 4 0 R
/Contents[2 0 R 8 0 R 3 0 R 2 0 R 901 0 R 3 0 R]
/Type
/Page
/Resources
<<
/ExtGState
<<
/GSa 6 0 R
>>
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/XObject
<<
/Im9 9 0 R
>>
/ColorSpace
<<
/CSp/DeviceRGB/CSpg/DeviceGray/PCSp 7 0 R
>>
/Font
<<
/F11 10 0 R
/F6 11 0 R
/Xi0 1 0 R
>>
>>
/MediaBox[0 0 595 842]
/Annots 12 0 R
>>
endobj
As you can see, I'm just altering the Contents array to insert my own data (an orange square with the object ID "901").
Is it possible to achieve the same result without parsing & modifying the original page object?
Since the /Contents array is a direct object, the entire page object is modified so you have to parse the page object and rewrite it with the new /Contents array.
If the /Contents would have been an indirect object then you could have modified only the array without touching the page object.

Is there a text string variable type in Adobe PDF specification?

In the below example (from gnupdf.org/Introduction_to_PDF; also related: How to generate plain-text source-code PDF examples that work in a document viewer?), text is written verbatim using:
(Hello, world!) Tj
Is there a way I could store this "Hello, world!" in a variable (dictionary?), say /MyStringVar, and then output it multiple places using something like:
(/MyStringVar) Tj
(I've tried the above, couldn't get it to work; /MyStringVar is interpreted verbatim)
Here is the code, hello.pdf:
%PDF-1.4
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/MediaBox [ 0 0 200 200 ]
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/Font <<
/F1 4 0 R
>>
>>
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
endobj
5 0 obj % page content
<<
/Length 44
>>
stream
BT
70 50 TD
/F1 12 Tf
(Hello, world!) Tj
ET
endstream
endobj
xref
0 6
0000000000 65535 f
0000000010 00000 n
0000000079 00000 n
0000000173 00000 n
0000000301 00000 n
0000000380 00000 n
trailer
<<
/Size 6
/Root 1 0 R
>>
startxref
492
%%EOF
The PDF does not have something like a variable like PostScript does. What may come close to what you are trying to achieve (output the same text multiple places) is a form XObject. Just like a page it has a content stream with graphics objects such as (Hello, world!) Tj, and it can be be drawn on a page (or another XObject) through the graphics Do operator. Its operand corresponds to a key in the XObject dictionary in the Resources dictionary of the page. The PDF would look something like this. (Note that stream lengths, the cross references table and the trailer or no longer valid so consider this pseudo-PDF.)
%PDF-1.4
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/MediaBox [ 0 0 200 200 ]
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/Font <<
/F1 4 0 R
>>
/XObject <<
/A 6 0 R % XObject /A is obj 6 0
>>
>> % /Resources must close here
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
endobj
5 0 obj % page content
<<
/Length 44
>>
stream
BT
70 50 TD % this has no effect on `/A Do` - only on the "manual" `Tj`
/A Do % do the drawing of XObject A
/F1 12 Tf % without this line: "Error: No font in show;"
% if without TD, then the next text is just appended
%-10 50 TD
0 0 TD % "Td/TD move to the start of next line"; but here like \r
(Hello, world - manual!) Tj
ET
endstream
endobj
6 0 obj
<< /Type /XObject
/Subtype /Form
/FormType 1
/BBox [ 0 0 1000 1000 ]
/Matrix [ 1 0 0 1 0 0 ]
/Resources << /ProcSet [ /PDF ] >>
/Length 58
>>
stream
%70 50 TD % without this `TD` setting, `/A Do` places this in 0,0 - bottom left corner
/F1 12 Tf
(Hello, world!) Tj
endstream
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000079 00000 n
0000000173 00000 n
0000000301 00000 n
0000000380 00000 n
0000000450 00000 n
trailer
<<
/Size 7
/Root 1 0 R
>>
startxref
600
%%EOF
Output in evince:
EDIT The text in the form XObject appears at the lower left corner because the current transformation matrix equals the identity matrix at the time of the show string operation. The initial CTM of the form XObject equals the concatenation of [the CTM in the parent stream when Do is invoked] and [the Matrix entry in the form XObject dictionary]. Which is identity in this case. The text matrix is not propagated from the parent stream to the form XObject.
As an addendum to #Frank's answer:
Deviations
There are some deviations from the PDF specification in the PDF in the answer.
in the page content stream (object 5) the XObject A is drawn from within a text object:
BT
70 50 TD % this has no effect on `/A Do` - only on the "manual" `Tj`
/A Do % do the drawing of XObject A
This is not allowed, cf. section 8.2, especially figure 9 at its end: XObjects may only be inserted at the page description level of the content of a page or XObject.
in the XObject content stream (object 6) a font is referenced
/F1 12 Tf
but no font resources are defined:
/Resources << /ProcSet [ /PDF ] >>
This is not allowed, The Tf operator shall specify the name of a font resource—that is, an entry in the Font subdictionary of the current resource dictionary (section 9.2.2 of the specification) which here is the resource dictionary of the XObject, not the page.
In very early versions of the PDF format a XObject could inherit resources of the page if it omitted the Resources entry... This construct is obsolete and should not be used by conforming writers (section 7.8.3 of the PDF specification) and in the example at hand, the Resources entry is not even omitted after all.
in the XObject content stream (object 6) the text showing operator Tj is used outside a text object:
stream
%70 50 TD % without this `TD` setting, `/A Do` places this in 0,0 - bottom left corner
/F1 12 Tf
(Hello, world!) Tj
endstream
This is not allowed, cf. section 8.2, especially figure 9 at its end: Text showing operators are only allowed in text objects, and as XObject shall not be used inside text objects, this stream cannot be considered to reside in one.
As it displays the XObject nonetheless, evince seems to be quite forgiving concerning PDF validity issues, even more forgiving than the Adobe Reader which already is very forgiving but shows that PDF as:
i.e. it does not display the XObject at all.
Adapted sample
This section contains an adapted sample which is nearer to the specification.
Furthermore the wish of the OP to position the XObject more freely is taken into account:
%PDF-1.4
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/MediaBox [ 0 0 200 200 ]
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/XObject <<
/A 6 0 R
>>
>>
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
endobj
5 0 obj % page content
<<
/Length 588
>>
stream
% draw xobject at 0, 0
/A Do
% draw xobject at 20, 180
q
1 0 0 1 20 180 cm
/A Do
Q
% draw xobject at 100, 100, with different scales and rotations applied
q
1 0 0 1 100 100 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
0.7 0.5 -0.5 0.7 0 0 cm
/A Do
Q
% draw xobject at 120, 180, skewed somewhat
q
1 0 0.3 1 120 180 cm
/A Do
Q
endstream
endobj
6 0 obj
<< /Type /XObject
/Subtype /Form
/FormType 1
/BBox [ 0 0 1000 1000 ]
/Matrix [ 1 0 0 1 0 0 ]
/Resources <<
/ProcSet [ /PDF ]
/Font <<
/F1 4 0 R
>>
>>
/Length 130
>>
stream
BT
/F1 12 Tf
% To not cut off stuff below the base line, namely parts of the comma
1 0 0 1 0 3 Tm
(Hello, world!) Tj
ET
endstream
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000079 00000 n
0000000173 00000 n
0000000301 00000 n
0000000380 00000 n
0000000450 00000 n
trailer
<<
/Size 7
/Root 1 0 R
>>
startxref
600
%%EOF
(Cross reference entries and stream lengths surely are wrong.)
This results (as seen in Adobe Reader):
All the "Hello, world!" instances are generated using the single XObject of the PDF.

Issue writing a PDF file from scratch

I'm trying to generate a simple PDF file (text only) programmatically.
With most PDF reader the file looks exactly like I want but some PDF readers won't open the file and report it as damaged.
I've removed every elements from the file leaving only the first void page to debug the code and found the problem but without any results, it's still recognized as damaged.
This is the raw PDF data:
%PDF-1.4
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<< /Type /Pages
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<< /Type /Page
/Parent 2 0 R
/Resources <<
>>
/MediaBox [ 0 0 595 842 ]
>>
endobj
xref
0 4
0000000000 65536 f
0000000010 00000 n
0000000067 00000 n
0000000138 00000 n
trailer
<< /Size 4
/Root 1 0 R
>>
startxref
248
%%EOF
Can anyone tell me what's wrong with this PDF?
Thanks in advance.
Per spec /Resources is required although it can be empty. Adding /Resources <<>> to object 2 or 3 should suffice.
EDIT
The PDF below with the updated /Resources entry passes Acrobat's preflight when I run it. Do you get a preflight error message?
%PDF-1.4
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<< /Type /Pages
/Count 1
/Kids [ 3 0 R ]
>>
endobj
3 0 obj
<< /Type /Page
/Parent 2 0 R
/MediaBox [ 0 0 595 842 ]
/Resources <<>>
>>
endobj
xref
0 4
0000000000 65536 f
0000000010 00000 n
0000000067 00000 n
0000000138 00000 n
trailer
<< /Size 4
/Root 1 0 R
>>
startxref
243
%%EOF