From 9d043aa1e110021b91593cdbea4954faf2572d46 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Tue, 20 Nov 2018 09:42:45 +0800 Subject: get id string and xml --- source/pdf/pdf-crypt.c | 194 +++++++++++++++++++++++++++++++++---------------- 1 file 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; } -- cgit v1.2.3