I have a .pfa font file and I would like to read the "algorithm" for rendering the font. However, most of the information is hidden in binary in the line:
currentfile eexec
743F8413F3636CA85A9FFEFB50B4BB27302A5F6C876586CCC1670A7EF5521E6ADE15AAB4
DD2DDDB83735311FC63DB80D2C96AECFA05BB67F865EA35934B4B79A203A8DD489B09C79
FF6EB9DBCFD889C3E73F8C94BC342AF671D6F688870A62EE1A0DF216E150FFEC64A8C2B7
509AD05C011599C1AD84E6C4B668E07EA219BD72663D8AF4CA8EC8E23AA90DE90BE940C6
6DB849CEDB3B64961365A7CCE47F4FC9E30FDEE4B14B90C2E0D8C344EBC974EABF417B3D
28251A78ACEE2BFC4212B1E3E9C7EBC3262821EE98E538713C64DF0BC13C19337B1307DB
D795D285F959C924FC14AEF7E9D406406CDEE1A35377887A16B13DD51717A86284369FA7
6ABB6A4488B9174A561DA854C33821F3172E4CF956EC9B65F829D69E02BC0EE23044DB1D
9A4D45A14A3998115BEE5DDC582F158DB2E..................
How do we "decode" this information?
Unless you really want to write your own eexec decryption, and then your own charstring decryption, I'd suggest you simply use t1disasm. If you are running on a Linux distribution you may be able to find a package for t1utils which should contain this, or you can get the source in a number of places (Google is your friend), here's one:
http://freepcb.googlecode.com/svn/clibpdf/trunk/util/t1utils-1.9/t1disasm.c
If you are on Windows you could look here for the t1utils package fopr WIndows :
http://gnuwin32.sourceforge.net/packages/t1utils.htm
I found this document very helpful in decrypting eexec encryption. A simple example in python using the code mentioned there.
#Getting the eexec binary, make sure you exclude the ascii part in the end, after the binary portion
text = open('fontfile.pfa').read()
raw_hex = text.split('eexec')[1]
decarr = list()
count = 0
hex_code = str()
#Converting pairs of the hexadecimal digits to decimal, e.g. ff -> 255, and storing it in an array decarr
for i in range(len(raw_hex)):
if raw_hex[i] == '\n':
decarr.append(raw_hex[i])
continue
else:
hex_code = hex_code + raw_hex[i]
count += 1
if count == 2:
decarr.append(int(hex_code, 16))
count = 0
hex_code = str()
Once we have an array of the decimal equivalents of pairs of hexadecimal digits, we perform decryption as mentioned in Chapter 7 of Adobe Type 1 Font Format Specification. The constants are as mentioned in the specification.
c1 = 52845
c2 = 22719
R = 55665
p = list()
for i in range(0,len(decarr)):
if decarr[i] is not '\n':
p.append(decarr[i]^(R >> 8))
R = ((decarr[i] + R)*c1 + c2) & ((1 << 16) - 1)
else:
p.append(decarr[i])
decrypted = list()
for i in range(len(p)):
if p[i] is not '\n':
decrypted.append(chr(p[i]))
else:
decrypted.append(p[i])
Hope it helps!
I think KenS's answer is better, but, as a curiosity, here is an emacs function that does eexec decryption of a bynary input (i.e. no decryption of hexadecimal input and no charstring decryption). The algorithm is from the document in Henry's answer.
(defun eexec-decrypt ()
"decrypt eexec binary block (see Type1 font);
NB: no charstring decryption"
(interactive)
(search-forward "currentfile eexec")(forward-char 1)
(with-output-to-temp-buffer (concat (buffer-name) "-eexec-decripted")
(setq r 55665)
(setq c1 52845)
(setq c2 22719)
(setq here (point))
(setq count 4)
(while (< here (point-max)) ; I'm not really sure where to stop...
(setq cipher (get-byte here))
(setq plain (logxor cipher (lsh r -8)))
(cond ((> count 0) ; skip first 4 bytes
(setq count (- count 1)))
(t (princ (byte-to-string plain))))
(setq r (mod (+ c2 (* c1 (+ cipher r))) 65536))
(setq here (+ 1 here)))))
What was really neat is that any patient seventh grader could sight read an eexec file!
Just insert a random character and view both your stack and your error report. Repeat every few dozen characters.
Like a voice response safe "try three clicks to the left".