PDF加密、解密内幕(二)- PDF文件口令加密内幕
0 几个重要概念
全局加密密钥,简称为全局密钥,该全局密钥由加密字典对象和你输入的口令生成,用来生成对象加密密钥。
对象加密密钥,简称为对象密钥,是用来实际加密PDF文件内容的密钥,不同于上篇PDF加密仿真里的全部的对象共用一个密钥不同,PDF文件中每个对象的加密密钥都不一样。
User Password 用户口令。
Owner password 权限口令。
1 PDF文件的加密流程
上一篇文章大致介绍了关于ACROBAT对PDF加密操作和加密后生成的PDF文件中的加密字典对象。同时我们提出了下面的四个问题:
1. 文件的内容是如何被加密的?
2. 加密密钥是如何生成的?
3. 加密字典中的每一项是如何生成的?
4. 加密字典和加密密钥的关系?
第一个问题是我们的最终目的,本文要最终要解决的就是这个问题。而第2,3,4个问题作为第1个问题的分解,在下文中有个清晰地解答。
下面是一个PDF文件加密的大致过程:
1. 选择PDF兼容版本和输入用户口令,权限口令。
2. 根据输入生成加密字典对象。
3. 由输入和加密字典对象生成全局密钥。
4. 由全局密钥生成对象加密密钥。
5. 用对象加密密钥加密对象内容。
2 PDF加密解密流程详解
加密字典对象一般有下面的条目:
/Length 密钥的长度
/Filter 生成密钥的方法,就是前面说的security handler
/O 是由用户口令和权限口令得到的,用来生成密钥和验证输入的权限口令
/P 访问权限的标志
/R 标准加密的(standard security handler)的版本
/U由用户口令生成,用来验证输入的用户口令或权限口令,是否要提醒用户输入密码
/V 可选,用来指明加密的算法。
一般来说这上面的条目是必须的,其它条目具体见PDF规范。这上面的加密字典条目中除了条目O和U之外其它的都可以直接生成。那么接下来我们就来看这两个条目,全局加密密钥,和对象加密密钥的生成过程。
如果你去看PDF规范,在有的步骤会有点迷茫的,相信下面的详细介绍对大家会有所帮助,如果你要实现自己的加密程序,也将给你一个指引。
2.1 生成加密字典和加密密钥
2.1.1 生成条目O
算法3.3:
1. 补充或截取权限口令字符串为32个字节。如果输入的口令大于32个字节,那么只保留前32个字节,如果少于32个字节,那么就按下面的字符串补上所缺少的字节数:
<0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x 8a , 0x41,
0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
0x 2f , 0x 0c , 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a>
如果没有权限(主)口令,那么就用用户口令替代。
2. 初始化MD5函数并将步骤1产生的结果输入MD5函数。
3. (版本3或更高)连续做50次:此后输出作为输入新的MD5哈希函数中。
4. 利用这个HASH数列的前面n位创建RC4密钥,对于版本2来说,n始终为5, 但对于版本3或更高版本来说,取决于加密字典中Length的值,为length/8。
5. 按照算法3.2中的第一步由用户口令得到32字节字符串。
6. 将第5步中产生的32位字节字符串用第4步中产生的密钥用RC4算法加密。
7. (版本3或更高)做19次:用前一次的输出作为下一次的输入进行编码;密钥是由第1步产生的原始密钥的单个字节和循环数和进行XOR(异或)运算得到的。
char Test[32] = 第1步生成的32字符串。
char temKey = Test[32];
unsigned int keyLength = length/8;
for (i = 1; i <=19; i++)
{
for (j = 0; j < keyLength; ++j)
{
tmpKey[j] = fileKey[j] ^ i;
}
rc4InitKey(tmpKey, keyLength, fState);
fx = fy = 0;
for (j = 0; j < 32; ++j)
{
test[j] = rc4EncryptByte(fState, &fx, &fy, test[j]);
}
}
8. 这32字节字符串即为加密字典对象条目O的值。
图1
2.1.2 得到全局加密密钥
算法2:
1. 补充或截取口令字符串为32个字节。如果输入的口令大于32个字节,那么只保留前32个字节,如果少于32个字节,那么就按下面的字符串补上所缺少的字节数:
<0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x 8a , 0x41,
0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
0x 2f , 0x 0c , 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a>
如果用户口令为空,那么就意味着没有用户口令,用这32个字节完全填充。
2.初始化MD5函数并将步骤1产生的结果输入MD5函数。
3.将加密字典O条目输入MD5中。(算法3.3描述O值的产生)。
4.将P条目作为无符号的4字节整数然后将该4字节输入MD5函数。
5.将该PDF文档的ID标识数组的第一个元素(即该PDF文档中trailer字典中ID条目的第一个字符串)输入到函数MD5中。(关于PDF文档ID的介绍见文章“PDF文档ID”)
6. (版本3或更高)如果该文档的metadata不加密,将4字节的0xFFFFFFFF输入哈希函数MD5中。
7.结束散列。
8.(版本3或更高)将前面MD5产生的HASH序列的前n位,也就是加密字典中的Length/8位字串,输入到新的MD5哈希函数中,此后输出作为输入连续再做49次。
9.加密密钥就是这个HASH数列的前面n位,对于版本2来说,n始终为5,对于版本3或更高版本来说,就取决于加密字典中Length的值,n=length/8。
这个算法,是根据用户口令字符串,产生全局加密密钥。
图2
2.1.3 生成条目U
算法4 版本2:
1 按照算法2的方法,基于用户口令字符串生成加密密钥。
2 用上面步骤产生的加密密钥加密按照算法2步骤1生成的32位串。
3 步骤2的输出即为加密字典对象中条目U的值。
算法5 版本3:
1按照算法2的方法,基于用户口令字符串生成加密密钥。
2 初始化MD5 HASH函数并将按照算法2步骤1生成的32位字符串输入该函数。
3 将文件ID数组中的第一个32位ID字串传入MD5函数。
4 用第1步产生的密钥通过RC4算法来加密由步骤3输出的16位字符串。
9. 做19次:用前一次的输出作为下一次的输入进行解码;密钥是由第1步产生的原始密钥的单个字节和循环数和进行XOR(异或)运算得到的。
char Test[32] = 第1步生成的32字符串。
char temKey = Test[32];
unsigned int keyLength = length/8;
for (i = 1; i <=19; i++)
{
for (j = 0; j < keyLength; ++j)
{
tmpKey[j] = fileKey[j] ^ i;
}
rc4InitKey(tmpKey, keyLength, fState);
fx = fy = 0;
for (j = 0; j < 32; ++j)
{
test[j] = rc4EncryptByte(fState, &fx, &fy, test[j]);
}
}
2.2 生成对象加密密钥并将对象加密
算法3.1 用RC4和AES对数据进行加密算法:
1.获得字符串对象或流对象的对象号(object number)和产生号(generation numer), 如果字符串对象是一个直接对象,则利用其包含该对象的标识符。
2.将对象号和产生号作2进制整数对待,将原始的N字节长的密匙扩展到n+5字节,即将对象号的低3个字节和产生号的低2个字节依次接在前面N字节长的加密K密钥上, 顺序为低字节靠前。(如果密钥的长度为40那么n为5,如果V的值大于1, n的值就为Length除以8。)
3.初始化MD5哈希函数,然后将步骤2产生的字符串输入到MD5中。
4.用前(n+5)个字节,如果N+5>16那么截取前面的16个字节,将这个产生的hash结果作为RC4和AES对称加密算法的密匙来对该字符串或流对象进行加密。
如果是用到AES算法,用到CBC模式。
图 3
3 回答云木的问题
云木的问题是这样,只有设置了权限口令的的PDF文件,是否可以直接从PDF文件中取出某个对象的流?
他想这样的PDF文件应该是不加密的,因为PDF文件的内容是可以看到的,只是设置了一个用来表示权限的串。这是我上篇文章《PDF文件加密仿真》中说的,而且还说了可以有办法去掉这个串或者修改这个串,不过我也有在文章中用红色字体说明PDF文件中内容实际上是加密了的,只是加密密钥可以从加密字典中直接计算出来。
那么这个密钥如何如何计算得到呢?我想由算法3.2和算法3.1就得出答案了。因为没有打开口令,那么直接由上面的32字节加密口令常量串填充,然后根据其它文件中的相关内容得到全局密钥。进而生成对象加密密钥。
4 是否可以直接修改权限设置串
有的人说可以直接修改加密字典中的条目P得到更大的权限,其实不然,因为按照加密算法2,全局加密密钥其中有个输入就是P, 如果P修改了,也不能正确得到加密密钥。你也可以实际试验一下,用 Ultra Edit打开,修改P条目,然后再用PDF reader打开,就会提示你输入口令,因为根据该PDF文件本身是无法得到加密密钥了。
5 本文总结
本文详细地对PDF文件的口令加密做了一个说明,相信你可以利用它来对PDF文件进行口令加密了,当然在一些细节方面你需要查询一下PDF规范。整篇文章采用多种方式来表达,目的只有一个,就是让整个内容显得非常明白容易理解。 在两个比较难懂的地方我用了伪码,我想这也会对你的理解有所帮助。
当然,错误是在所难免的,如果你对文章有什么意见,或者有什么知道,或者你认为怎样会更好,那么我非常希望你能给我来信或者给我评论和留言。
非常感谢!
PDF加密、解密内幕(二)- PDF文件口令加密内幕相关推荐
- 【加密解密】对exe文件的加密解密 含源代码》
//编译环境VS2013#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #includ ...
- PDF加密、解密内幕(二) - PDF文件口令加密内幕
PDF加密.解密内幕(二) - PDF文件口令加密内幕 0 几个重要概念 全局加密密钥,简称为全局密钥,该全局密钥由加密字典对象和你输入的口令生成,用来生成对象加密密钥. 对象加密密钥,简称为对象密钥 ...
- IOS之RSA加密解密与后台之间的双向加密详解
IOS之RSA加密解密与后台之间的双向加密详解 序言 因为项目中需要用到RSA加密,刚开始也是有点乱,这两天也整理的差不多了,希望能帮到大家. 这次先上代码,我想大部分人肯定是着急解决问题,所以不要废 ...
- 文件夹加密软件哪个好?文件夹加密软件排行榜
想要加密文件夹,使用专业的文件夹加密软件可以安全有效地加密电脑文件夹.那么,文件夹加密软件哪个好?文件夹加密软件排行榜了解一下. TOP 1:文件夹加密超级大师 软件亮点:极致安全,5种文件夹加密类型 ...
- 文件夹加密软件怎么选?文件夹加密软件盘点
文件夹是电脑储存数据的重要工具,那么该如何保护文件夹的数据安全呢?使用合适的文件夹加密软件可能是最简单的方法.那么文件夹加密软件该怎么选呢? 文件夹加密超级大师 文件夹加密超级大师可以说是最全能的文件 ...
- php 密匙加密解密,带密匙的php加密解密示例分享
这篇文章主要介绍了php加密解密示例,大家参考使用吧 复制代码 代码如下: /************************************************************* ...
- 【Kotlin】加密解密2:DES、AES加密和解密
文章目录 Api文档 DES加密解密 Base64加密和解密 AES加密解密 DES和AES密钥长度 工作模式和填充模式 对称加密的应用场景 Api文档 https://docs.oracle.com ...
- php结合md5的加密解密,php结合md5实现的加密解密方法,php结合md5加密解密_PHP教程...
php结合md5实现的加密解密方法,php结合md5加密解密 本文实例讲述了php结合md5实现的加密解密方法.分享给大家供大家参考,具体如下: 最近在整理代码发现了一个不错的东西,结合md5的加解密 ...
- c语言解密pdf,C语言设计-英文加密解密系统资料.pdf
昆明理工大学 <程序设计基础>课程 综合设计实践教学课题报告 课程名称: C 语言设计 课题名称: 英文加密解密系统 组长: 学号 姓名 组员: 学号 姓名: 学号 姓名 学院: 专业班级 ...
最新文章
- Chapter5_初始化与清理_enum关键字
- 2016各大公司校招薪水曝光:年薪28万,这只是零花钱
- C结构体工具DirectStruct(综合示例二)
- 在线实时大数据平台Storm集成redis开发(分布锁)
- zookeeper命令
- [转载]流行视频格式讲解
- Photoshop Blendmodi in GLSL
- 企业网站 源码 e-mail_临汾网站制作,B2B软件哪家好
- 字符串includes_字符串操作大全:面试准备和日常编码所需一文打尽
- 转SQLSERVER 会不会自动加锁
- 8. jQuery 效果 - 动画
- 一个校园网络的规划与设计
- CMD 命令 复制多级子目录特定文件
- 独木桥的c语言程序,独木桥
- 没想到一个起点中文网都可以掀起这么大的波澜
- AcWing 741. 斐波那契数列
- 淘宝直播详细开通方法
- Word 题注重新编号
- 站在物联网风口 中兴着力构建GIA 的IoT新生态
- YoloV4当中的Mosaic数据增强方法(附代码讲解)