dotnet Open XML 如何判断一份 Office 文档是否被加密
在拿到一份 PPTX 文档,或一份 Word 的 docx 文档,如何判断这份文档是被加密的
在 Office 里,对 pptx 文档或 docx 或 xlsx 文档的加密是将文档加密为 OLE 格式,也就是和 Office 2003 的 doc 等文档格式相同的 Ole object 格式
在没加密时,是使用 OPC 格式,也就是 zip 压缩文档。但是加密之后,文档格式使用 OLE Object 格式,就不能用 OpenXML SDK 读取。因为 OpenXML SDK 将使用压缩文档读取方法读取,这个方法不能读取 OLE 文件
如果使用 OpenXML SDK 读取一个加密的 Office 文档,那么将会在读取的时候抛出 OpenXmlPackageException 告诉开发者失败
可以使用 openmcdf 这个开源库读取 OLE 文件,然后判断这个文件是否 Office 加密文件
判断一份文档是否被加密首先需要了解加密的格式,请看 [MS-OFFCRYPTO]: Office Document Cryptography Structure
先创建一份加密的 pptx 文档,接下来尝试判断这个文件是加密的 Office 文件,我在 github 放一份我创建的文件,小伙伴可以随意使用
最简单的方法就是通过 OpenXML SDK 读一下文档,如果抛出 OpenXmlPackageException 那么也许就是被加密了
如果想要通过读取 OLE 判断的方法,需要先在项目里面安装 openmcdf 库
<ItemGroup>
<PackageReference Include="OpenMcdf" Version="2.2.1.6" />
</ItemGroup>
然后添加下面代码
private static bool CheckOfficeDocumentWithPassword(FileInfo file)
{
CompoundFile cf = new CompoundFile(file.FullName);
var numDirectories = cf.GetNumDirectories();
for (int i = 0; i < numDirectories; i++)
{
var nameDirEntry = cf.GetNameDirEntry(i);
if (cf.RootStorage.TryGetStream(nameDirEntry, out var stream))
{
if (nameDirEntry == "EncryptionInfo")
{
return true;
}
}
}
return false;
}
使用方法如下
static void Main(string[] args)
{
var file = @"带密码的课件PPTX.pptx";
if (CheckOfficeDocumentWithPassword(new FileInfo(file)))
{
Console.WriteLine("带密码");
}
}
本文代码放在 github 欢迎小伙伴访问
这个方法判断的原理是加密的 Office 文件里面,将会是 OLE 格式,而 OLE 是一个磁盘格式,可以理解为和 zip 差不多的格式,加密的文件里面将会包含下面内容
而在 Office 的解密方法就是使用用户输入的密码和 EncryptionInfo 内容判断,然后解压缩 EncryptedPackage 文件,所以上面的判断大概是对的
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Spark UDF加载外部资源
- Flink SQL FileSystem Connector 分区提交与自定义小文件合并策略
- Facebook面试题: 用递归和迭代手写Array.prototype.flat()
- Kubernetes插件之ip-masq-agent
- 抽丝剥茧Kotlin - 协程
- 使用Java8中的Optional类来消除代码中的null检查
- 通俗讲解从Transformer到BERT模型!
- 「R」使用有限混合模型
- Kaggle经典数据分析项目:泰坦尼克号生存预测!
- 零基础学习梯度下降算法
- Spring JPA 依赖配置
- Spring JPA 核心概念
- Spring JPA 查询
- 初学者指南:利用SVD创建推荐系统
- 聊一聊面试中经常被问到的Tree Shaking