mirror of
				https://github.com/michaelrsweet/pdfio.git
				synced 2025-10-31 10:26:22 +01:00 
			
		
		
		
	Add support for EncryptMetadata key in encryption dictionary.
This commit is contained in:
		| @@ -98,7 +98,7 @@ static uint8_t pdf_passpad[32] =	// Padding for passwords | ||||
|  | ||||
| static void	decrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]); | ||||
| static void	encrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]); | ||||
| static void	make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, uint8_t file_key[16]); | ||||
| static void	make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, bool encrypt_metadata, uint8_t file_key[16]); | ||||
| static void	make_owner_key(pdfio_encryption_t encryption, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]); | ||||
| static void	make_user_key(const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]); | ||||
| static void	pad_password(const char *password, uint8_t pad[32]); | ||||
| @@ -158,7 +158,7 @@ _pdfioCryptoLock( | ||||
|         // Generate the encryption key | ||||
|         file_id = pdfioArrayGetBinary(pdf->id_array, 0, &file_idlen); | ||||
|  | ||||
|         make_file_key(encryption, permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->file_key); | ||||
|         make_file_key(encryption, permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->encrypt_metadata, pdf->file_key); | ||||
| 	pdf->file_keylen = 16; | ||||
|  | ||||
| 	// Generate the user key... | ||||
| @@ -583,6 +583,7 @@ _pdfioCryptoUnlock( | ||||
|   _pdfio_md5_t	md5;			// MD5 context | ||||
|   uint8_t	file_digest[16];	// MD5 digest of file ID and pad | ||||
|   double	p;			// Permissions value as a double | ||||
|   _pdfio_value_t *value;		// Encrypt dictionary value, if any | ||||
|  | ||||
|  | ||||
|   // See if we support the type of encryption specified by the Encrypt object | ||||
| @@ -598,7 +599,12 @@ _pdfioCryptoUnlock( | ||||
|   revision = (int)pdfioDictGetNumber(encrypt_dict, "R"); | ||||
|   length   = (int)pdfioDictGetNumber(encrypt_dict, "Length"); | ||||
|  | ||||
|   PDFIO_DEBUG("_pdfioCryptoUnlock: handler=%p(%s), version=%d, revision=%d, length=%d\n", (void *)handler, handler ? handler : "(null)", version, revision, length); | ||||
|   if ((value = _pdfioDictGetValue(encrypt_dict, "EncryptMetadata")) != NULL && value->type == PDFIO_VALTYPE_BOOLEAN) | ||||
|     pdf->encrypt_metadata = value->value.boolean; | ||||
|   else | ||||
|     pdf->encrypt_metadata = true; | ||||
|  | ||||
|   PDFIO_DEBUG("_pdfioCryptoUnlock: handler=%p(%s), version=%d, revision=%d, length=%d, encrypt_metadata=%s\n", (void *)handler, handler ? handler : "(null)", version, revision, length, pdf->encrypt_metadata ? "true" : "false"); | ||||
|  | ||||
|   if (!handler || strcmp(handler, "Standard")) | ||||
|   { | ||||
| @@ -768,7 +774,7 @@ _pdfioCryptoUnlock( | ||||
|       make_owner_key(pdf->encryption, pad, pdf->owner_key, user_pad); | ||||
|       PDFIO_DEBUG("_pdfioCryptoUnlock: Upad=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_pad[0], user_pad[1], user_pad[2], user_pad[3], user_pad[28], user_pad[29], user_pad[30], user_pad[31]); | ||||
|  | ||||
|       make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, file_key); | ||||
|       make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->encrypt_metadata, file_key); | ||||
|       PDFIO_DEBUG("_pdfioCryptoUnlock: Fown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); | ||||
|  | ||||
|       make_user_key(file_id, file_idlen, own_user_key); | ||||
| @@ -786,7 +792,7 @@ _pdfioCryptoUnlock( | ||||
|       } | ||||
|  | ||||
|       // Not the owner password, try the user password... | ||||
|       make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, file_key); | ||||
|       make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, pdf->encrypt_metadata, file_key); | ||||
|       PDFIO_DEBUG("_pdfioCryptoUnlock: Fuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); | ||||
|  | ||||
|       make_user_key(file_id, file_idlen, own_user_key); | ||||
| @@ -918,6 +924,8 @@ make_file_key( | ||||
|     size_t              file_idlen,	// I - Length of file ID | ||||
|     const uint8_t       *user_pad,	// I - Padded user password | ||||
|     const uint8_t       *owner_key,	// I - Owner key | ||||
|     bool                encrypt_metadata, | ||||
| 					// I - Encrypt metadata? | ||||
|     uint8_t             file_key[16])	// O - Encryption key | ||||
| { | ||||
|   size_t	i;			// Looping var | ||||
| @@ -931,13 +939,25 @@ make_file_key( | ||||
|   perm_bytes[2] = (uint8_t)(permissions >> 16); | ||||
|   perm_bytes[3] = (uint8_t)(permissions >> 24); | ||||
|  | ||||
|   PDFIO_DEBUG("make_file_key: user_pad[32]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", user_pad[0], user_pad[1], user_pad[2], user_pad[3], user_pad[28], user_pad[29], user_pad[30], user_pad[31]); | ||||
|   PDFIO_DEBUG("make_file_key: owner_key[32]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", owner_key[0], owner_key[1], owner_key[2], owner_key[3], owner_key[28], owner_key[29], owner_key[30], owner_key[31]); | ||||
|   PDFIO_DEBUG("make_file_key: permissions(%d)=<%02X%02X%02X%02X>\n", permissions, perm_bytes[0], perm_bytes[1], perm_bytes[2], perm_bytes[3]); | ||||
|  | ||||
|   _pdfioCryptoMD5Init(&md5); | ||||
|   _pdfioCryptoMD5Append(&md5, user_pad, 32); | ||||
|   _pdfioCryptoMD5Append(&md5, owner_key, 32); | ||||
|   _pdfioCryptoMD5Append(&md5, perm_bytes, 4); | ||||
|   _pdfioCryptoMD5Append(&md5, file_id, file_idlen); | ||||
|   if (!encrypt_metadata) | ||||
|   { | ||||
|     uint8_t meta_bytes[4] = { 0xff, 0xff, 0xff, 0xff }; | ||||
| 					// Metadata bytes | ||||
|     _pdfioCryptoMD5Append(&md5, meta_bytes, 4); | ||||
|   } | ||||
|   _pdfioCryptoMD5Finish(&md5, digest); | ||||
|  | ||||
|   PDFIO_DEBUG("make_file_key: first md5=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", digest[0], digest[1], digest[2], digest[3], digest[12], digest[13], digest[14], digest[15]); | ||||
|  | ||||
|   if (encryption != PDFIO_ENCRYPTION_RC4_40) | ||||
|   { | ||||
|     // MD5 the result 50 times.. | ||||
| @@ -949,6 +969,8 @@ make_file_key( | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   PDFIO_DEBUG("make_file_key: file_key[16]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", digest[0], digest[1], digest[2], digest[3], digest[12], digest[13], digest[14], digest[15]); | ||||
|  | ||||
|   memcpy(file_key, digest, 16); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1262,6 +1262,8 @@ pdfioFileSetPermissions( | ||||
|   if (encryption == PDFIO_ENCRYPTION_NONE) | ||||
|     return (true); | ||||
|  | ||||
|   pdf->encrypt_metadata = true; | ||||
|  | ||||
|   return (_pdfioCryptoLock(pdf, permissions, encryption, owner_password, user_password)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -507,7 +507,7 @@ _pdfioObjLoad(pdfio_obj_t *obj)		// I - Object | ||||
|   } | ||||
|  | ||||
|   // Decrypt as needed... | ||||
|   if (obj->pdf->encryption) | ||||
|   if (obj->pdf->encryption && obj->pdf->encrypt_metadata) | ||||
|   { | ||||
|     PDFIO_DEBUG("_pdfioObjLoad: Decrypting value...\n"); | ||||
|  | ||||
|   | ||||
| @@ -271,6 +271,7 @@ struct _pdfio_file_s			// PDF file structure | ||||
| 		*cp1252_obj,		// CP1252 font encoding object | ||||
| 		*unicode_obj;		// Unicode font encoding object | ||||
|   pdfio_array_t	*id_array;		// ID array | ||||
|   bool		encrypt_metadata;	// Encrypt metadata? | ||||
|  | ||||
|   // Allocated data elements | ||||
|   size_t	num_arrays,		// Number of arrays | ||||
|   | ||||
		Reference in New Issue
	
	Block a user