summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2018-11-20 09:42:45 +0800
committerIru Cai <mytbk920423@gmail.com>2018-11-20 09:42:45 +0800
commit9d043aa1e110021b91593cdbea4954faf2572d46 (patch)
tree26b2ef5370e3037281b37107e138be10d4898375
parent881093d08030ebd50663919097f491cbea7d4fe8 (diff)
downloadmupdf-9d043aa1e110021b91593cdbea4954faf2572d46.tar.xz
get id string and xml
-rw-r--r--source/pdf/pdf-crypt.c194
1 files changed, 132 insertions, 62 deletions
diff --git a/source/pdf/pdf-crypt.c b/source/pdf/pdf-crypt.c
index 53dc73b5..a8a1bdb5 100644
--- a/source/pdf/pdf-crypt.c
+++ b/source/pdf/pdf-crypt.c
@@ -68,18 +68,8 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
crypt->xjc = 0;
if (!strcmp("ProfXJC", pdf_to_name(ctx, obj)))
{
- unsigned char akey[] = "\xCE\x69\x16\xAC\xD3\xA5\x00\x85\xF2\xD0\x22\x2A\x9C\xCE\x64\x4F\x65\xDF\x47\xE4\xE3\x6C\x24\x2B\x1B\x31\x6A\x3D\x3B\xE2\x20\xCC";
-
- crypt->encrypt_metadata = 0;
crypt->xjc = 1;
- crypt->length = 256;
- memcpy(crypt->key, akey, 32);
- crypt->stmf.method = PDF_CRYPT_AESV3;
- crypt->stmf.length = crypt->length;
- crypt->strf.method = PDF_CRYPT_AESV3;
- crypt->strf.length = crypt->length;
- return crypt;
- }
+ } else
if (!pdf_name_eq(ctx, PDF_NAME(Standard), obj))
{
pdf_drop_crypt(ctx, crypt);
@@ -90,7 +80,7 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
obj = pdf_dict_get(ctx, dict, PDF_NAME(V));
if (pdf_is_int(ctx, obj))
crypt->v = pdf_to_int(ctx, obj);
- if (crypt->v != 1 && crypt->v != 2 && crypt->v != 4 && crypt->v != 5)
+ if (!crypt->xjc && crypt->v != 1 && crypt->v != 2 && crypt->v != 4 && crypt->v != 5)
{
pdf_drop_crypt(ctx, crypt);
fz_throw(ctx, FZ_ERROR_GENERIC, "unknown encryption version");
@@ -98,58 +88,60 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
/* Standard security handler (PDF 1.7 table 3.19) */
- obj = pdf_dict_get(ctx, dict, PDF_NAME(R));
- if (pdf_is_int(ctx, obj))
- crypt->r = pdf_to_int(ctx, obj);
- else if (crypt->v <= 4)
- {
- fz_warn(ctx, "encryption dictionary missing revision value, guessing...");
- if (crypt->v < 2)
- crypt->r = 2;
- else if (crypt->v == 2)
- crypt->r = 3;
- else if (crypt->v == 4)
- crypt->r = 4;
- }
- else
- {
- pdf_drop_crypt(ctx, crypt);
- fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing version and revision value");
- }
- if (crypt->r < 1 || crypt->r > 6)
- {
- int r = crypt->r;
- pdf_drop_crypt(ctx, crypt);
- fz_throw(ctx, FZ_ERROR_GENERIC, "unknown crypt revision %d", r);
- }
+ if (!crypt->xjc) {
+ obj = pdf_dict_get(ctx, dict, PDF_NAME(R));
+ if (pdf_is_int(ctx, obj))
+ crypt->r = pdf_to_int(ctx, obj);
+ else if (crypt->v <= 4)
+ {
+ fz_warn(ctx, "encryption dictionary missing revision value, guessing...");
+ if (crypt->v < 2)
+ crypt->r = 2;
+ else if (crypt->v == 2)
+ crypt->r = 3;
+ else if (crypt->v == 4)
+ crypt->r = 4;
+ }
+ else
+ {
+ pdf_drop_crypt(ctx, crypt);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing version and revision value");
+ }
+ if (crypt->r < 1 || crypt->r > 6)
+ {
+ int r = crypt->r;
+ pdf_drop_crypt(ctx, crypt);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "unknown crypt revision %d", r);
+ }
- obj = pdf_dict_get(ctx, dict, PDF_NAME(O));
- if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) == 32)
- memcpy(crypt->o, pdf_to_str_buf(ctx, obj), 32);
- /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
- else if (crypt->r >= 5 && pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) >= 48)
- memcpy(crypt->o, pdf_to_str_buf(ctx, obj), 48);
- else
- {
- pdf_drop_crypt(ctx, crypt);
- fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing owner password");
- }
+ obj = pdf_dict_get(ctx, dict, PDF_NAME(O));
+ if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) == 32)
+ memcpy(crypt->o, pdf_to_str_buf(ctx, obj), 32);
+ /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
+ else if (crypt->r >= 5 && pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) >= 48)
+ memcpy(crypt->o, pdf_to_str_buf(ctx, obj), 48);
+ else
+ {
+ pdf_drop_crypt(ctx, crypt);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing owner password");
+ }
- obj = pdf_dict_get(ctx, dict, PDF_NAME(U));
- if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) == 32)
- memcpy(crypt->u, pdf_to_str_buf(ctx, obj), 32);
- /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
- else if (crypt->r >= 5 && pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) >= 48)
- memcpy(crypt->u, pdf_to_str_buf(ctx, obj), 48);
- else if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) < 32)
- {
- fz_warn(ctx, "encryption password key too short (%d)", pdf_to_str_len(ctx, obj));
- memcpy(crypt->u, pdf_to_str_buf(ctx, obj), pdf_to_str_len(ctx, obj));
- }
- else
- {
- pdf_drop_crypt(ctx, crypt);
- fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing user password");
+ obj = pdf_dict_get(ctx, dict, PDF_NAME(U));
+ if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) == 32)
+ memcpy(crypt->u, pdf_to_str_buf(ctx, obj), 32);
+ /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
+ else if (crypt->r >= 5 && pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) >= 48)
+ memcpy(crypt->u, pdf_to_str_buf(ctx, obj), 48);
+ else if (pdf_is_string(ctx, obj) && pdf_to_str_len(ctx, obj) < 32)
+ {
+ fz_warn(ctx, "encryption password key too short (%d)", pdf_to_str_len(ctx, obj));
+ memcpy(crypt->u, pdf_to_str_buf(ctx, obj), pdf_to_str_len(ctx, obj));
+ }
+ else
+ {
+ pdf_drop_crypt(ctx, crypt);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "encryption dictionary missing user password");
+ }
}
obj = pdf_dict_get(ctx, dict, PDF_NAME(P));
@@ -272,6 +264,84 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
crypt->length = crypt->stmf.length;
}
+ if (crypt->xjc) {
+#if 0
+ unsigned char akey[] = "\xCE\x69\x16\xAC\xD3\xA5\x00\x85\xF2\xD0\x22\x2A\x9C\xCE\x64\x4F\x65\xDF\x47\xE4\xE3\x6C\x24\x2B\x1B\x31\x6A\x3D\x3B\xE2\x20\xCC";
+#endif
+ fz_sha256 sha256;
+ fz_sha256 xml_hash;
+ unsigned char xml_hash_sum[32];
+ unsigned char *r_buf = NULL;
+ size_t r_size = 0;
+
+ // crypt->encrypt_metadata = 0;
+ obj = pdf_dict_get(ctx, dict, PDF_NAME(Length));
+ if (pdf_is_int(ctx, obj))
+ crypt->length = pdf_to_int(ctx, obj);
+
+ crypt->stmf.method = PDF_CRYPT_AESV3;
+ crypt->stmf.length = crypt->length;
+ crypt->strf.method = PDF_CRYPT_AESV3;
+ crypt->strf.length = crypt->length;
+
+ fz_sha256_update(&sha256, "ProfXJC.General", 15);
+ fz_warn(ctx, "crypt method: %d, crypt length: %d, crypt perm: %x",
+ crypt->stmf.method, crypt->length, crypt->p);
+ fz_sha256_update(&sha256, &crypt->stmf.method, 4);
+ fz_sha256_update(&sha256, &crypt->length, 4);
+ fz_sha256_update(&sha256, &crypt->p, 4);
+
+ obj = pdf_dict_gets(ctx, dict, "Recipients");
+ if (pdf_is_string(ctx, obj)) {
+ unsigned char idstr[32];
+ int l = pdf_to_str_len(ctx, obj);
+
+ if (pdf_is_array(ctx, id) && pdf_array_len(ctx, id) == 2)
+ {
+ crypt->id = id;
+ }
+ if (pdf_is_array(ctx, crypt->id)) {
+ pdf_obj *oid;
+ size_t osz;
+ const char *buf;
+
+ oid = pdf_array_get(ctx, crypt->id, 0);
+ buf = pdf_to_string(ctx, oid, &osz);
+ if (osz == 16) {
+ memcpy(idstr, buf, 16);
+ } else {
+ fz_warn(ctx, "length of id[0] is %ld", osz);
+ }
+ oid = pdf_array_get(ctx, crypt->id, 1);
+ buf = pdf_to_string(ctx, oid, &osz);
+ if (osz == 16) {
+ memcpy(idstr + 16, buf, 16);
+ } else {
+ fz_warn(ctx, "length of id[1] is %ld", osz);
+ }
+ }
+ r_buf = fz_malloc(ctx, l);
+ memcpy(r_buf, pdf_to_str_buf(ctx, obj), l);
+ unsigned char tmpbyte = 0xff;
+ int ididx = 0;
+ for (int i = 0; i < l; i++) {
+ tmpbyte ^= idstr[ididx];
+ ididx = (ididx + 1) % 32;
+ r_buf[i] ^= tmpbyte;
+ // printf("%c", r_buf[i]);
+ }
+ }
+ /* hash some weird thing */
+ /* hash an XML */
+ fz_sha256_init(&xml_hash);
+ /* hash an XML */
+ fz_sha256_final(&xml_hash, xml_hash_sum);
+ fz_sha256_update(&sha256, xml_hash_sum, 32);
+ fz_sha256_final(&sha256, crypt->key);
+
+ // memcpy(crypt->key, akey, 32); /* TODO: kill this */
+ return crypt;
+ }
return crypt;
}