- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将 .p7s 字节数组信息插入签名字段,我按照下面的图片:
我的步骤:
准备签名容器
原始PDF为“tmp/example.pdf”,这部分输出为“results/prepared.pdf”
PdfSigner signer = new PdfSigner(new PdfReader("tmp/example.pdf"), new FileStream("results/prepared.pdf", FileMode.Create), new StampingProperties().UseAppendMode());
signer.SetFieldName("Signature1");
PdfDocument _pdfDocument = new PdfDocument(new PdfReader("tmp/example.pdf"));
PdfSignatureAppearance sigAppearance = signer.GetSignatureAppearance();
sigAppearance
.SetPageRect(new Rectangle(144, 144, 200, 100))
.SetPageNumber(1)
.SetContact("This is contact")
.SetReason("This is reason")
.SetLocation("This is location")
.SetSignatureCreator("This is signature creator");
MyExternalSignatureContainer _container = new MyExternalSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached, _chain);
IExternalSignatureContainer container = _container;
signer.SignExternalContainer(container, 8192);
byte[] _sb = _container.Signed_Bytes;
我的外部签名容器类
public byte[] Sign(Stream data)
{
iText.Signatures.PdfPKCS7 _sgn = new iText.Signatures.PdfPKCS7(null, chain, "SHA256", false);
byte[] _hash = iText.Signatures.DigestAlgorithms.Digest(data, "SHA256");
byte[] _sh = _sgn.GetAuthenticatedAttributeBytes(_hash, PdfSigner.CryptoStandard.CMS,
null, null);
Signed_Bytes = _sh;
return new byte[0]; ;
}
直到这一部分,一切顺利,我得到了“results/prepared.pdf”哈希并发送到外部签名服务并获得.p7s
现在我想根据上图将 .p7s byte[] 插入到 PDF 结构的签名值部分。
我尝试使用下面的代码获取“results/prepared.pdf”的 PdfDictionay
的 ByteRange
信息,我希望将 .p7s 注入(inject)到签名容器中“results/injected.pdf”中的“results/prepared.pdf”
PdfDocument pdfDocument = new PdfDocument(new PdfReader("results/prepared.pdf"), new PdfWriter("results/injected.pdf").SetSmartMode(true));
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
PdfSignature signature = signatureUtil.GetSignature("Signature1");
PdfDictionary _pd = signatureUtil.GetSignatureDictionary("Signature1");
现在我得到“_pd”的结果如下:
{<</ByteRange [0 107457 123843 2688 ] /ContactInfo This is contact /Contents
我的理解(如果我错了请纠正我)是我应该把 .p7s 字节数组放在 107457 作为起始位置。
尝试将 .p7s 注入(inject)现有的签名容器
我尝试制作下面的 paddedSig
数组并将 .p7s 复制到它:
byte[] _p7s = System.IO.File.ReadAllBytes("tmp/example.p7s");
byte[] paddedSig = new byte[8192];
System.Array.Copy(_p7s, 0, paddedSig, 0, _p7s.Length);
然后尝试将 paddedSig 放入 PdfDictionary,如下所示:
PdfDictionary _pd = signatureUtil.GetSignatureDictionary("Signature1");
pd.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true));
pdfDocument.Close();
生成了一个名为“results/injected.pdf”的新 PDF,但是:
Signature contains incorrect, unrecognized, corrupted or suspicious data. Support Information: SigDict /Contents illegal data
我错过了什么? .. 如何将.p7s 注入(inject)准备好的签名容器?
回复 Mkl 的帖子:
我不明白的是如何将返回的 PKCS#7 字节嵌入到 pdf 中。假设 byte[] _p7s 是 API_CALL 的结果
byte[] _p7s = API_CALL;
byte[] paddedSig = new byte[8192];
System.Array.Copy(_p7s, 0, paddedSig, 0, _p7s.Length);
然后尝试将 paddedSig 放入 PdfDictionary,如下所示:
PdfDictionary _pd = signatureUtil.GetSignatureDictionary("Signature1");
pd.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true));
pdfDocument.Close();
结果是:
签名包含不正确、无法识别、损坏或可疑的数据。支持信息:SigDict/Contents illegal data
尝试使用 .p7s 文件
我有一个 example.p7s 文件,我尝试使用下面提供的代码嵌入:
byte[] _p7s = System.IO.File.ReadAllBytes("tmp/example.p7s");
private static void Embed_P7S(Org.BouncyCastle.X509.X509Certificate[] _chain, byte[] _p7s)
{
PdfDocument document = new PdfDocument(new PdfReader("results/example-prepared.pdf"));
Stream output = new FileStream("results/example-prepared-signed.pdf", FileMode.Create);
ExternalInjectingSignatureContainer container2 = new ExternalInjectingSignatureContainer(_p7s);
PdfSigner.SignDeferred(document, "Signature1", output, container2);
}
}
internal class ExternalInjectingSignatureContainer :IExternalSignatureContainer
{
public ExternalInjectingSignatureContainer(byte[] signature)
{
Signature = signature;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
}
public byte[] Sign(Stream data)
{
return Signature;
}
public byte[] Signature;
}
结果:
example-prepared-signed.pdf 未显示证书(这类似于原始 pdf)但尺寸比原始 pdf 大
original.pdf 为 105KB示例准备的是 124KBexample-prepared-signed 是 121KB
最佳答案
首先,您不必像现在这样拆分签名过程。我已经看到很多开发人员想要这样做的问题,但严格来说没有必要(嗯,在引擎盖下 iText 仍然会首先创建一个准备好的 PDF,然后注入(inject)签名容器,但它可以保留在引擎盖下)。
只有当外部签名服务需要很长时间才能创建签名并且您无法在内存中保存 PDF 时,才需要拆分流程。
我将在此处研究这两种变体。
如果您的外部签名服务足够快地返回结果(一个完整的 PKCS#7 签名容器),您应该使用这种方法。基本代码的开头与您的相似:
PdfSigner signer = new PdfSigner(new PdfReader("example.pdf"), new FileStream("example-signed.pdf", FileMode.Create), new StampingProperties().UseAppendMode());
signer.SetFieldName("Signature1");
PdfSignatureAppearance sigAppearance = signer.GetSignatureAppearance();
sigAppearance
.SetPageRect(new Rectangle(144, 144, 200, 100))
.SetPageNumber(1)
.SetContact("This is contact")
.SetReason("This is reason")
.SetLocation("This is location")
.SetSignatureCreator("This is signature creator");
ExternalServiceSignatureContainer container = new ExternalServiceSignatureContainer();
signer.SignExternalContainer(container, 8192);
您的代码的区别在于 IExternalSignatureContainer
实现:
public class ExternalServiceSignatureContainer : IExternalSignatureContainer
{
public void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite);
signDic.Put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached);
}
public byte[] Sign(Stream data)
{
// Call your external signing service to create a CMS signature container
// for the data in the InputStream and return that signature container
[... see below ...]
}
}
根据您访问外部签名服务的 API,Sign
的实现会有所不同。在每种情况下,我都假设 API_CALL 将结果 PKCS#7 签名容器作为字节数组返回:
您可以直接通过流调用它
return YOUR_SIGNING_API_CALL_FOR_STREAM(data);
或者使用从流内容生成的 byte[]
return YOUR_SIGNING_API_CALL_FOR_ARRAY(StreamUtil.InputStreamToArray(data));
作为参数,
或者您可能首先必须自己对数据进行哈希处理(例如如下所示)并将您的哈希发送到服务。
byte[] hash = DigestAlgorithms.Digest(data, DigestAlgorithms.SHA256);
return YOUR_SIGNING_API_CALL_FOR_HASH(hash)
signer
的输出已经是最终确定的签名 PDF。
这本质上是已经在 this answer 中讨论过的情况。 .
如果您的外部签名服务没有足够快地返回结果(一个完整的 PKCS#7 签名容器)(例如,在批量签名 API 的情况下,或者在服务等待确认的情况下,如果需要很长时间)或者如果在你这边,你在调用签名服务之前实现了这一部分,之后在单独的程序中实现了这一部分(有些人确实这样做了),你可以使用这种方法。
同样,基本代码的开头与您的相似:
PdfSigner signer = new PdfSigner(new PdfReader("example.pdf"), new FileStream("example-prepared.pdf", FileMode.Create), new StampingProperties().UseAppendMode());
signer.SetFieldName("Signature1");
PdfSignatureAppearance sigAppearance = signer.GetSignatureAppearance();
sigAppearance
.SetPageRect(new Rectangle(144, 144, 200, 100))
.SetPageNumber(1)
.SetContact("This is contact")
.SetReason("This is reason")
.SetLocation("This is location")
.SetSignatureCreator("This is signature creator");
ExternalEmptySignatureContainer container = new ExternalEmptySignatureContainer();
signer.SignExternalContainer(container, 8192);
byte[] dataToSign = container.Data;
ExternalEmptySignatureContainer
现在只提供稍后签名服务签名的数据,还没有注入(inject)签名容器
public class ExternalEmptySignatureContainer : IExternalSignatureContainer
{
public void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite);
signDic.Put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached);
}
public byte[] Sign(Stream data)
{
// Store the data to sign and return an empty array
[... see below ...]
return new byte[0];
}
public byte[] Data;
}
根据您访问外部签名服务的 API,Sign
的实现会有所不同。
如果您的签名 API 需要原始数据进行签名,请使用从流内容生成的 byte[]
Data = StreamUtil.InputStreamToArray(data);
如果您的签名 API 需要原始数据的哈希值进行签名,请从流内容中像这样计算
Data = DigestAlgorithms.Digest(data, DigestAlgorithms.SHA256);
signer
的输出是中介,准备好的 PDF。
下一步是调用签名服务并检索 PKCS#7 签名容器:
byte[] signature = YOUR_SIGNING_API_CALL(dataToSign);
最后,您将该签名容器注入(inject)到准备好的 PDF 中:
PdfDocument document = new PdfDocument(new PdfReader("example-prepared.pdf"));
using (Stream output = new FileStream("example-prepared-signed.pdf", FileMode.Create))
{
ExternalInjectingSignatureContainer container2 = new ExternalInjectingSignatureContainer(signature);
PdfSigner.SignDeferred(document, "Signature1", output, container2);
}
IExternalSignatureContainer
实现仅注入(inject)签名字节:
public class ExternalInjectingSignatureContainer : IExternalSignatureContainer
{
public ExternalInjectingSignatureContainer(byte[] signature)
{
Signature = signature;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
}
public byte[] Sign(Stream data)
{
return Signature;
}
public byte[] Signature;
}
输出是最终确定的、签名的 PDF。
关于c# - 如何使用 iText7 将 .p7s 字节数组插入到 PDF 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61811135/
我有 512 行要插入到数据库中。我想知道提交多个插入内容是否比提交一个大插入内容有任何优势。例如 1x 512 行插入 -- INSERT INTO mydb.mytable (id, phonen
已经提出了类似的问题,但由于它总是取决于,我单独询问我的具体情况。 我有一个网站页面,显示来自数据库的一些数据,要从该数据库生成数据,我必须执行一些相当复杂的多连接查询。 数据每天(每晚)更新一次。
我正在使用 MongoDb 和 MySQL 的 python 连接器 pymongo 和 pymysql 测试 MongoDb 和 MySQL,特别是插入功能。 pymongo版本是3.4,pymys
从 C# 应用程序插入大型数组(10M 元素)的最快方法是什么? 到目前为止,我使用的是批量插入。 C# 应用程序生成一个大文本文件,我使用 BULK INSERT 命令加载它。出于好奇,我编写了一个
我编写了一个枚举类型,当我为它运行我创建的 JUnit 测试时会出现以下语法错误: java.lang.Error: Unresolved compilation problems: Synt
我正在尝试创建一个程序,它将单词列表作为输入,并将它们排序为二叉树,以便能够找到它们,例如像字典。这是我到目前为止所做的,但是 newEl -> el = input; 出现段错误,我知道这是因为它试
你好 我有编译这个问题 \begin{equation} J = \sum_{j=1}^{C} \end{equation} 我不断收到错误 missing $ inserted 这很奇怪,因
我需要使用 LINQ to SQL 将记录插入到没有主键的表中。 table 设计得很差;我无法控制表结构。该表由几个 varchar 字段、一个文本字段和一个时间戳组成。它用作其他实体的审计跟踪。
我正在尝试使用 itextsharp 创建 Pdf。我添加了一张包含两列的表格,其中一列包含文本和其他图像。我想要恒定的图像大小 如果另一个单元格中的文本增加并且其他单元格中的图像大小不同,我的图像会
我想把 calory 作为 fruits 的第一个值,我做不到,有人能帮忙吗? $sql = 'INSERT INTO fruits VALUES('', ?, ?, ?)'
我有一个包含季度观察结果的 data.frame。我现在想插入每月值(首选三次,线性很好)。中间目标应该是使用 DATE 创建一个 data.frame作为所有每月观察的索引和缺失值。 谷歌搜索表明我
我想知道是否有办法在值列表中使用“插入”。我正在尝试这样做: insert into tblMyTable (Col1, Col2, Col3) values('value1', value
我想让人们能够在他们的网站中插入单个 Javascript 行,这实际上允许我插入包含我网站内容的固定大小的 IFRAME。它实际上是一个小部件,允许他们搜索我的网站或接收其他信息。这可能吗? 最佳答
我有一个包含时间的表,列名为 time,数据类型为 Date。 在 asp.net 中,我想要一个查询插入日期,另一个查询则在 2 个日期之间进行选择。 我已经尝试过这个: string data =
这是我的代码: create or replace trigger th after insert on stock for each row declare sqty number;
这是一个带有具体示例的通用问题。 我有一个包含三个字段(流派 ID (PK IDENTITY)、流派和子流派)的表。该表对(流派,子流派)组合具有唯一约束。 我想知道如何修改存储过程以在表中不存在时插
因此,我正在遍历二叉树,节点包含字符串,以及读取文件时该字符串是否出现多次。我只查找读取文件时出现次数最多的前 10 个单词,因此本质上我只是比较 int 值。 我的问题是我正在尝试找出一种有效的方法
我有一张机票和行李 map , 每张门票必须是唯一的,并且必须与 map 上的位置相对应 是否可以仅更改行李(m_bagage->秒)而不更改 key ? std::unordered_map m_c
我正在使用 jdbc 驱动程序做一个示例项目。我的问题是,如果我在 2 文本字段中输入空值。 null 不应该加载到数据库中吗?有没有办法避免在数据库中插入空字段?任何帮助将不胜感激。 //Execu
我想知道 SSIS 中是否有特定的插入或更新选项。 如果我想让程序检查它是更新还是插入,我是否必须做一些编码?或者是否可以启用一个选项,以便它会自行检查 PK 是否存在,然后更新,否则插入? 亲切的问
我是一名优秀的程序员,十分优秀!