30
30
import numpy as np
31
31
32
32
from matplotlib .cbook import _format_approx
33
+ from . import _api
33
34
34
35
35
36
# token types
@@ -46,10 +47,12 @@ class Type1Font:
46
47
parts : tuple
47
48
A 3-tuple of the cleartext part, the encrypted part, and the finale of
48
49
zeros.
50
+ decrypted : bytes
51
+ The decrypted form of parts[1].
49
52
prop : dict[str, Any]
50
53
A dictionary of font properties.
51
54
"""
52
- __slots__ = ('parts' , 'prop' )
55
+ __slots__ = ('parts' , 'decrypted' , ' prop' )
53
56
54
57
def __init__ (self , input ):
55
58
"""
@@ -68,6 +71,7 @@ def __init__(self, input):
68
71
data = self ._read (file )
69
72
self .parts = self ._split (data )
70
73
74
+ self .decrypted = self ._decrypt (self .parts [1 ], 'eexec' )
71
75
self ._parse ()
72
76
73
77
def _read (self , file ):
@@ -139,6 +143,54 @@ def _split(self, data):
139
143
_token_re = re .compile (br'/{0,2}[^]\0\t\r\v\n ()<>{}/%[]+' )
140
144
_instring_re = re .compile (br'[()\\]' )
141
145
146
+ @staticmethod
147
+ def _decrypt (ciphertext , key , ndiscard = 4 ):
148
+ """
149
+ Decrypt ciphertext using the Type-1 font algorithm
150
+
151
+ The algorithm is described in Adobe's "Adobe Type 1 Font Format".
152
+ The key argument can be an integer, or one of the strings
153
+ 'eexec' and 'charstring', which map to the key specified for the
154
+ corresponding part of Type-1 fonts.
155
+
156
+ The ndiscard argument should be an integer, usually 4.
157
+ That number of bytes is discarded from the beginning of plaintext.
158
+ """
159
+
160
+ key = _api .check_getitem ({'eexec' : 55665 , 'charstring' : 4330 }, key = key )
161
+ plaintext = []
162
+ for byte in ciphertext :
163
+ plaintext .append (byte ^ (key >> 8 ))
164
+ key = ((key + byte ) * 52845 + 22719 ) & 0xffff
165
+
166
+ return bytes (plaintext [ndiscard :])
167
+
168
+ @staticmethod
169
+ def _encrypt (plaintext , key , ndiscard = 4 ):
170
+ """
171
+ Encrypt plaintext using the Type-1 font algorithm
172
+
173
+ The algorithm is described in Adobe's "Adobe Type 1 Font Format".
174
+ The key argument can be an integer, or one of the strings
175
+ 'eexec' and 'charstring', which map to the key specified for the
176
+ corresponding part of Type-1 fonts.
177
+
178
+ The ndiscard argument should be an integer, usually 4. That
179
+ number of bytes is prepended to the plaintext before encryption.
180
+ This function prepends NUL bytes for reproducibility, even though
181
+ the original algorithm uses random bytes, presumably to avoid
182
+ cryptanalysis.
183
+ """
184
+
185
+ key = _api .check_getitem ({'eexec' : 55665 , 'charstring' : 4330 }, key = key )
186
+ ciphertext = []
187
+ for byte in b'\0 ' * ndiscard + plaintext :
188
+ c = byte ^ (key >> 8 )
189
+ ciphertext .append (c )
190
+ key = ((key + c ) * 52845 + 22719 ) & 0xffff
191
+
192
+ return bytes (ciphertext )
193
+
142
194
@classmethod
143
195
def _tokens (cls , text ):
144
196
"""
0 commit comments