Skip to content

Commit

Permalink
Recrypt finished
Browse files Browse the repository at this point in the history
  • Loading branch information
johnwhitington committed Nov 6, 2014
1 parent 49b2df3 commit d12025a
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 97 deletions.
129 changes: 68 additions & 61 deletions pdfcrypt.ml
Expand Up @@ -4,6 +4,10 @@ open Pdfio

let crypt_debug = ref false

let nums pdf =
Pdf.objiter (fun n _ -> Printf.printf "%n " n) pdf;
flprint "\n"

(* Given an object number, generation number, input key and key length in bits,
apply Algorithm 3.1 from the PDF Reference manual to obtain the hash to be used
by the encryption function. *)
Expand Down Expand Up @@ -1088,11 +1092,57 @@ let is_encrypted pdf =
(* recrypt_pdf pdf password re-encrypts a PDF document which was decrypted with
the user or owner password given using that same user password *)
let recrypt_pdf_user pdf pw =
let pdf = Pdf.renumber (Pdf.changes pdf) pdf in
let (crypt_type, u, o, p, id, ue, oe), encrypt_metadata, perms =
match pdf.Pdf.saved_encryption with
None -> raise (Pdf.PDFError "recrypt_pdf: no saved encryption")
| Some x -> (x.Pdf.from_get_encryption_values, x.Pdf.encrypt_metadata, x.Pdf.perms)
let (crypt_type, u, o, p, id, ue, oe), encrypt_metadata, perms =
match pdf.Pdf.saved_encryption with
None -> raise (Pdf.PDFError "recrypt_pdf: no saved encryption")
| Some x -> (x.Pdf.from_get_encryption_values, x.Pdf.encrypt_metadata, x.Pdf.perms)
in
match crypt_type with
| Pdf.AESV3 iso ->
let oe =
match oe with
Some oe -> oe
| None -> raise (Pdf.PDFError "recrypt_pdf: bad /oe")
and ue =
match ue with
Some ue -> ue
| None -> raise (Pdf.PDFError "recrypt_pdf: bad /ue")
in
let key =
if authenticate_user_password_aesv3 iso (make_utf8 pw) u
then file_encryption_key_aesv3_user iso (make_utf8 pw) u ue
else raise (Pdf.PDFError "recrypt_pdf: failed AESV3 fek.")
in
encrypt_pdf_AES256_inner
iso encrypt_metadata o u p perms oe ue id
(string_of_bytes key) pdf
| Pdf.AESV2 ->
encrypt_pdf_AES_inner o u p pw id encrypt_metadata pdf
| Pdf.ARC4 (40, _) ->
encrypt_pdf_40bit_inner o u p pw id pdf
| Pdf.ARC4 (128, 4) ->
encrypt_pdf_128bit_inner_r4 o u p pw id pdf encrypt_metadata
| Pdf.ARC4 (128, _) ->
encrypt_pdf_128bit_inner o u p pw id pdf
| _ -> raise (Pdf.PDFError "recrypt_pdf: bad encryption")

(* recrypt_pdf_owner password re-encrypts a PDF document which was decrypted with
the user or owner password given using that same owner password *)
let recrypt_pdf_owner pdf owner_pw =
let (crypt_type, u, o, p, id, ue, oe), encrypt_metadata, perms =
match pdf.Pdf.saved_encryption with
None ->
raise (Pdf.PDFError "recrypt_pdf: no saved encryption")
| Some x ->
(x.Pdf.from_get_encryption_values, x.Pdf.encrypt_metadata, x.Pdf.perms)
in
let key, pw =
match
key_or_user_password_from_owner
~encryption_values:(crypt_type, u, o, oe) owner_pw pdf
with
None -> raise (Pdf.PDFError "Recrypt with owner password failed.")
| Some (key, pw) -> (key, pw)
in
match crypt_type with
| Pdf.AESV3 iso ->
Expand All @@ -1105,14 +1155,8 @@ let recrypt_pdf_user pdf pw =
Some ue -> ue
| None -> raise (Pdf.PDFError "recrypt_pdf: bad /ue")
in
let key =
if authenticate_user_password_aesv3 iso (make_utf8 pw) u
then file_encryption_key_aesv3_user iso (make_utf8 pw) u ue
else raise (Pdf.PDFError "recrypt_pdf: failed AESV3 fek.")
in
encrypt_pdf_AES256_inner
iso encrypt_metadata o u p perms oe ue id
(string_of_bytes key) pdf
encrypt_pdf_AES256_inner
iso encrypt_metadata o u p perms oe ue id key pdf
| Pdf.AESV2 ->
encrypt_pdf_AES_inner o u p pw id encrypt_metadata pdf
| Pdf.ARC4 (40, _) ->
Expand All @@ -1121,53 +1165,16 @@ let recrypt_pdf_user pdf pw =
encrypt_pdf_128bit_inner_r4 o u p pw id pdf encrypt_metadata
| Pdf.ARC4 (128, _) ->
encrypt_pdf_128bit_inner o u p pw id pdf
| _ -> raise (Pdf.PDFError "recrypt_pdf: bad encryption")
| _ -> raise (Pdf.PDFError "recrypt_pdf_owner: bad encryption")

(* recrypt_pdf_owner password re-encrypts a PDF document which was decrypted with
the user or owner password given using that same owner password *)
let recrypt_pdf_owner pdf owner_pw =
let pdf = Pdf.renumber (Pdf.changes pdf) pdf in
let (crypt_type, u, o, p, id, ue, oe), encrypt_metadata, perms =
match pdf.Pdf.saved_encryption with
None ->
raise (Pdf.PDFError "recrypt_pdf: no saved encryption")
| Some x ->
(x.Pdf.from_get_encryption_values, x.Pdf.encrypt_metadata, x.Pdf.perms)
in
let key, pw =
match
key_or_user_password_from_owner
~encryption_values:(crypt_type, u, o, oe) owner_pw pdf
with
None -> raise (Pdf.PDFError "Recrypt with owner password failed.")
| Some (key, pw) -> (key, pw)
in
match crypt_type with
| Pdf.AESV3 iso ->
let oe =
match oe with
Some oe -> oe
| None -> raise (Pdf.PDFError "recrypt_pdf: bad /oe")
and ue =
match ue with
Some ue -> ue
| None -> raise (Pdf.PDFError "recrypt_pdf: bad /ue")
in
encrypt_pdf_AES256_inner
iso encrypt_metadata o u p perms oe ue id key pdf
| Pdf.AESV2 ->
encrypt_pdf_AES_inner o u p pw id encrypt_metadata pdf
| Pdf.ARC4 (40, _) ->
encrypt_pdf_40bit_inner o u p pw id pdf
| Pdf.ARC4 (128, 4) ->
encrypt_pdf_128bit_inner_r4 o u p pw id pdf encrypt_metadata
| Pdf.ARC4 (128, _) ->
encrypt_pdf_128bit_inner o u p pw id pdf
| _ -> raise (Pdf.PDFError "recrypt_pdf_owner: bad encryption")

let recrypt_pdf pdf pw =
try
try recrypt_pdf_user pdf pw with _ -> recrypt_pdf_owner pdf pw
with
_ -> raise (Pdf.PDFError "recrypt_pdf failed. Wrong password?")
let recrypt_pdf ?(renumber=true) pdf pw =
Printf.printf "******************************************recrypt_pdf, renumber = %b\n" renumber;
let pdf =
if renumber then Pdf.renumber (Pdf.changes pdf) pdf
else pdf
in
try
try recrypt_pdf_user pdf pw with _ -> recrypt_pdf_owner pdf pw
with
_ -> raise (Pdf.PDFError "recrypt_pdf failed. Wrong password?")

2 changes: 1 addition & 1 deletion pdfcrypt.mli
Expand Up @@ -36,7 +36,7 @@ val is_encrypted : Pdf.t -> bool
(** [recrypt_pdf decrypted_and_modified] re-encrypts a PDF document
which was decrypted using the user password and owner password from the
original encrypted file and the same permissions and encryption parameters. *)
val recrypt_pdf : Pdf.t -> string -> Pdf.t
val recrypt_pdf : ?renumber:bool -> Pdf.t -> string -> Pdf.t

(** Encrypt a PDF documnent, using 40 bit encryption, with given user and
owner passwords. *)
Expand Down
58 changes: 23 additions & 35 deletions pdfwrite.ml
Expand Up @@ -579,15 +579,11 @@ let dummy_encryption =

(* Flatten a PDF document to an Pdfio.output. *)
let pdf_to_output
?(preserve_objstm = false) ?(generate_objstm = false) ?(compress_objstm = true)
?(recrypt = None)
linearize encrypt pdf o
?(preserve_objstm = false) ?(generate_objstm = false)
?(compress_objstm = true) ?(recrypt = None) linearize encrypt pdf o
=
if !write_debug then
begin
flprint "****pdf_to_output\n";
debug_whole_pdf pdf
end;
begin flprint "****pdf_to_output\n"; debug_whole_pdf pdf end;
if !write_debug then
Printf.printf "pdf_to_output: preserve %b, generate %b, linearize %b\n"
preserve_objstm generate_objstm linearize;
Expand All @@ -609,10 +605,7 @@ let pdf_to_output
([], false) (* Weren't asked to preserve, or nothing to put in streams *)
in
if !write_debug then
begin
flprint "****after object streams built\n";
debug_whole_pdf pdf
end;
begin flprint "****after object streams built\n"; debug_whole_pdf pdf end;
let encrypt =
match recrypt with
None -> encrypt
Expand All @@ -632,26 +625,24 @@ let pdf_to_output
in
if !write_debug then flprint "Finished renumber\n";
if !write_debug then
begin
flprint "****after renumbering\n";
debug_whole_pdf pdf
end;
begin flprint "****after renumbering\n"; debug_whole_pdf pdf end;
let pdf =
match recrypt with
None -> pdf
| Some pw -> Pdfcrypt.recrypt_pdf pdf pw
| Some pw ->
Pdfcrypt.recrypt_pdf
~renumber:(not (preserve_objstm || generate_objstm)) pdf pw
in
if !write_debug then
begin flprint "****just before crypt_if_necessary\n"; debug_whole_pdf pdf end;
let pdf = crypt_if_necessary pdf encrypt in
if !write_debug then
begin
flprint "crypt_if_necessary done...\n";
if Pdfcrypt.is_encrypted pdf then flprint "FILE IS ENCRYPTED\n"
end;
if !write_debug then
begin
flprint "****crypted, ready to write\n";
debug_whole_pdf pdf
end;
begin flprint "****crypted, ready to write\n"; debug_whole_pdf pdf end;
o.output_string (header pdf);
let xrefs = ref []
and objiter =
Expand Down Expand Up @@ -734,15 +725,11 @@ let change_id pdf f =

(* Write a PDF to a channel. Don't use mk_id when the file is encrypted.*)
let pdf_to_channel
?(preserve_objstm = false)
?(generate_objstm = false)
?(compress_objstm = true)
?(recrypt = None)
?(preserve_objstm = false) ?(generate_objstm = false)
?(compress_objstm = true) ?(recrypt = None)
linearize encrypt mk_id pdf ch
=
let pdf =
if mk_id then change_id pdf "" else pdf
in
let pdf = if mk_id then change_id pdf "" else pdf in
pdf_to_output
~preserve_objstm ~generate_objstm ~compress_objstm ~recrypt
linearize encrypt pdf (output_of_channel ch)
Expand All @@ -754,18 +741,19 @@ existing object streams will be preserved. If [generate_objstm] is set, new
ones will be generated in addition. To get totally fresh object streams, set
[preserve_objstm=false, generate_objstm=true]. *)
let pdf_to_file_options
?(preserve_objstm = false)
?(generate_objstm = false)
?(compress_objstm = true)
?(recrypt = None)
?(preserve_objstm = false) ?(generate_objstm = false)
?(compress_objstm = true) ?(recrypt = None)
linearize encrypt mk_id pdf f
=
let pdf' = if mk_id then change_id pdf f else pdf
and ch = open_out_bin f in
pdf_to_channel
~preserve_objstm ~generate_objstm ~compress_objstm ~recrypt
linearize encrypt false pdf' ch;
close_out ch
try
pdf_to_channel
~preserve_objstm ~generate_objstm ~compress_objstm ~recrypt
linearize encrypt false pdf' ch;
close_out ch
with
e -> close_out ch; raise e

let pdf_to_file pdf f =
pdf_to_file_options
Expand Down

0 comments on commit d12025a

Please sign in to comment.