1#!/bin/env python
2#Copyright ReportLab Europe Ltd. 2000-2017
3#see license.txt for license details
4__version__='3.3.0'
5__doc__="""Testing to encrypt a very minimal pdf using a Canvas and a DocTemplate.
6TODO: Automatiocally test that this pdf is really encrypted.
7"""
8import unittest
9from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation
10setOutDir(__name__)
11from reportlab.pdfgen.canvas import Canvas
12from reportlab.lib import pdfencrypt
13from reportlab.lib.styles import ParagraphStyle
14from reportlab.platypus import SimpleDocTemplate, Paragraph
15
16def parsedoc(fileName):
17    """
18    Using PDFParseContext object from Pagecatcher module to check for encryption.
19    """
20    try:
21        from rlextra.pageCatcher.pageCatcher import PDFParseContext
22    except ImportError:
23        return
24    pdfContent = open(fileName, 'rb').read()
25    p = PDFParseContext(pdfContent, prefix="PageForms")
26    p.parse()
27    assert p.encrypt
28
29def testStdEnc(expectedO,expectedU,expectedKey,
30                strength=40, overrideID='xxxxxxxxxxxxxxxx',
31                userPass='User',ownerPass='Owner',
32                ):
33    # do a 40 bit example known to work in Acrobat Reader 4.0
34    enc = pdfencrypt.StandardEncryption(userPass,ownerPass, strength=strength)
35    enc.setAllPermissions(0)
36    enc.canPrint = 1
37    enc.prepare(None,overrideID)
38
39    pdfencrypt.equalityCheck(pdfencrypt.hexText(enc.O),expectedO, '%d bit O value'%strength)
40    pdfencrypt.equalityCheck(pdfencrypt.hexText(enc.U),expectedU, '%d bit U value'%strength)
41    pdfencrypt.equalityCheck(pdfencrypt.hexText(enc.key),expectedKey, '%d bit key value'%strength)
42
43class EncryptTestCase(unittest.TestCase):
44
45    def test_canvas(self):
46        "Test generating an encrypted pdf by setting a user password on the Canvas."
47        fname = outputfile('test_encrypt_canvas.pdf')
48        c = Canvas(fname, encrypt='User')
49        c.setAuthor('Anonymous')
50        c.setFont('Helvetica-Bold', 36)
51        c.drawString(100,700, 'Top secret')
52        c.save()
53        parsedoc(fname)
54
55    def test_standardencryption(self):
56        "Test generating an encrypted pdf by passing a StandardEncryption object to the Canvas."
57        encrypt = pdfencrypt.StandardEncryption(userPassword='User', ownerPassword='Owner')
58        encrypt.setAllPermissions(0)
59        encrypt.canPrint = 1
60        fname = outputfile('test_encrypt_canvas2.pdf')
61        c = Canvas(fname, encrypt=encrypt)
62        c.setAuthor('Anonymous')
63        c.setFont('Helvetica-Bold', 36)
64        c.drawString(100,700, 'Top secret')
65        c.save()
66        parsedoc(fname)
67
68    def test_doctemplate(self):
69        "Test generating an encrypted pdf by setting a user password on the DocTemplate."
70        header = ParagraphStyle(name='Heading', fontSize=36)
71        story = [Paragraph("Top secret", header)]
72        fname = outputfile('test_encrypt_doctemplate.pdf')
73        doc = SimpleDocTemplate(fname, encrypt='User')
74        doc.build(story)
75        parsedoc(fname)
76
77    def test_standardencryption128(self):
78        "Test generating an encrypted pdf by passing a StandardEncryption object to the Canvas."
79        encrypt = pdfencrypt.StandardEncryption(userPassword='User', ownerPassword='Owner',strength=128)
80        encrypt.setAllPermissions(0)
81        encrypt.canPrint = 1
82        fname = outputfile('test_encrypt_canvas2_128.pdf')
83        c = Canvas(fname, encrypt=encrypt)
84        c.setAuthor('Anonymous')
85        c.setFont('Helvetica-Bold', 36)
86        c.drawString(100,700, 'More Top secret uses 128 bit encryption!')
87        c.save()
88        parsedoc(fname)
89
90    def test_calcs(self):
91        testStdEnc(
92                expectedO = '<FA7F558FACF8205D25A7F1ABFA02629F707AE7B0211A2BB26F5DF4C30F684301>',
93                expectedU = '<4E6F35A0356D6A624A72387D71FFB92EA4457E435307A9DD0BA9DE0618F5BABD>',
94                expectedKey = '<DC96439AD9>',
95                strength=40, overrideID='xxxxxxxxxxxxxxxx',
96                userPass='User',ownerPass='Owner',
97                )
98        testStdEnc(
99                expectedO = '<E60E73846B1C9EB09986B2C20DEAEF48BCC2210F75AE640655EDDFF8B67E7DD6>',
100                expectedU = '<D9E804E73FB37EDECF35176140304BD600000000000000000000000000000000>',
101                expectedKey = '<7C0C9D27068EB81B291698B2CC278A48>',
102                strength=128, overrideID='xxxxxxxxxxxxxxxx',
103                userPass='User',ownerPass='Owner',
104                )
105        testStdEnc(
106                expectedO = '<FA7F558FACF8205D25A7F1ABFA02629F707AE7B0211A2BB26F5DF4C30F684301>',
107                expectedU = '<CB749297C89784B4BC94228F38B5FD4318398CA68F327A615A6CD8A5FCDB8C52>',
108                expectedKey = '<1528D3A2F9>',
109                strength=40, overrideID=b'\xbf\x08\xdf\x96I\x959e\x8f\x03\xcb\xb4\x11 W\xa9',
110                userPass='User',ownerPass='Owner',
111                )
112        testStdEnc(
113                expectedO = '<E60E73846B1C9EB09986B2C20DEAEF48BCC2210F75AE640655EDDFF8B67E7DD6>',
114                expectedU = '<9A823CD6C39CEA508577319287621BF800000000000000000000000000000000>',
115                expectedKey = '<6F8DB99AA5D9693CA757C2F03DAB71FF>',
116                strength=128, overrideID=b'\xbf\x08\xdf\x96I\x959e\x8f\x03\xcb\xb4\x11 W\xa9',
117                userPass='User',ownerPass='Owner',
118                )
119
120def makedoc(fileName, userPass="User", ownerPass="Owner"):
121    """
122    Creates a simple encrypted pdf.
123    """
124    encrypt = pdfencrypt.StandardEncryption(userPass, ownerPass)
125    encrypt.setAllPermissions(0)
126    encrypt.canPrint = 1
127
128    c = Canvas(fileName)
129    c._doc.encrypt = encrypt
130
131    c.drawString(100, 500, "hello world")
132
133    c.save()
134
135class ManualTestCase(unittest.TestCase):
136    "Runs manual encrypted file builders."
137
138    def test(self):
139        filepath = outputfile('test_pdfencryption.pdf')
140        makedoc(filepath)
141        parsedoc(filepath)
142
143def makeSuite():
144    return makeSuiteForClasses(EncryptTestCase,ManualTestCase)
145
146
147#noruntests
148if __name__ == "__main__":
149    unittest.TextTestRunner().run(makeSuite())
150    printLocation()
151