From 35c5c76c53466af4b3cf594fb27c435ce058c252 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Tue, 20 Nov 2018 12:14:41 +0800 Subject: the complete hashing, but not works --- source/pdf/pdf-crypt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/source/pdf/pdf-crypt.c b/source/pdf/pdf-crypt.c index cc333039..e98f8989 100644 --- a/source/pdf/pdf-crypt.c +++ b/source/pdf/pdf-crypt.c @@ -3,6 +3,8 @@ #include #include +#include +#include typedef struct { @@ -102,8 +104,28 @@ void mt19937_init(mt19937 *ctx, uint32_t seed) ctx->MT[0] = seed; for (int i = 1; i < 624; i++) { - ctx->MT[i] = 0x6c078965 * (ctx->MT[i] ^ (ctx->MT[i-1] >> 30)) + i; + ctx->MT[i] = 0x6c078965UL * (ctx->MT[i] ^ (ctx->MT[i-1] >> 30)) + i; + } +} + +uint32_t hex_to_dword(const char *hex) +{ + uint32_t result = 0; + for (int i = 0; i < 4; i++) { + uint32_t t = 0; + for (int j = 0; j < 2; j++) { + t *= 16; + if (hex[j] >= '0' && hex[j] <= '9') + t += hex[j] - '0'; + else if (hex[j] >= 'A' && hex[j] <= 'F') + t += hex[j] - 'A' + 10; + else if (hex[j] >= 'a' && hex[j] <= 'f') + t += hex[j] - 'a' + 10; + } + result |= (t << (i * 8)); + hex += 2; } + return result; } enum @@ -376,6 +398,7 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id) unsigned char xml_hash_sum[32]; unsigned char *r_buf = NULL; size_t r_size = 0; + mt19937 mtctx; // crypt->encrypt_metadata = 0; obj = pdf_dict_get(ctx, dict, PDF_NAME(Length)); @@ -433,7 +456,30 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id) r_buf[i] ^= tmpbyte; } } - /* hash some weird thing */ + + const char *sseed = strstr(r_buf, "Seed=\""); + if (!sseed) { + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot find the seed"); + } + uint32_t seed = strtoll(sseed + 6, NULL, 10); + mt19937_init(&mtctx, seed); + + const char *userpass = strstr(r_buf, ""); + if (!userpass) { + fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot find UserPassword"); + } + userpass += 18; + + uint32_t tmpword = 0xffffffff; + uint32_t pass[0x20]; + for (int i = 0; i < 0x20; i++) { + tmpword ^= mt19937_next(&mtctx); + uint32_t dw = hex_to_dword(userpass); + userpass += 8; + pass[i] = dw ^ tmpword; + } + + fz_sha256_update(&sha256, pass, 0x80); fz_sha256_update(&sha256, r_buf, r_size); fz_sha256_init(&xml_hash); -- cgit v1.2.3