3030import numpy as np
3131
3232from matplotlib .cbook import _format_approx
33+ from . import _api
3334
3435
3536# token types
@@ -46,10 +47,12 @@ class Type1Font:
4647 parts : tuple
4748 A 3-tuple of the cleartext part, the encrypted part, and the finale of
4849 zeros.
50+ decrypted : bytes
51+ The decrypted form of parts[1].
4952 prop : dict[str, Any]
5053 A dictionary of font properties.
5154 """
52- __slots__ = ('parts' , 'prop' )
55+ __slots__ = ('parts' , 'decrypted' , ' prop' )
5356
5457 def __init__ (self , input ):
5558 """
@@ -68,6 +71,7 @@ def __init__(self, input):
6871 data = self ._read (file )
6972 self .parts = self ._split (data )
7073
74+ self .decrypted = self ._decrypt (self .parts [1 ], 'eexec' )
7175 self ._parse ()
7276
7377 def _read (self , file ):
@@ -139,6 +143,54 @@ def _split(self, data):
139143 _token_re = re .compile (br'/{0,2}[^]\0\t\r\v\n ()<>{}/%[]+' )
140144 _instring_re = re .compile (br'[()\\]' )
141145
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+
142194 @classmethod
143195 def _tokens (cls , text ):
144196 """
0 commit comments