C# iText7(.net)SignExternalSignatureContainer NullReferenceException
我正在尝试创建一个能对PDF文档进行数字签名的C# iText7(.net)SignExternalSignatureContainer NullReferenceException,c#,digital-signature,nullreferenceexception,itext7,C#,Digital Signature,Nullreferenceexception,Itext7,我正在尝试创建一个能对PDF文档进行数字签名的C程序。为了将签名元素包含到PDF中,我使用了iText7。 现在,如果我在没有调试器的情况下运行程序,将抛出一个System.NullReferenceException,程序将失败。但是如果我用调试器运行程序,也会发生异常,代码会继续并正确地签署PDF 我不确定这是否是iText7的问题,或者我在创建签名字段时是否犯了错误或忘记了一些重要的事情 有什么办法解决这个问题吗 例外情况 System.NullReferenceException:Der
C
程序。为了将签名元素包含到PDF中,我使用了iText7
。
现在,如果我在没有调试器的情况下运行程序,将抛出一个System.NullReferenceException
,程序将失败。但是如果我用调试器运行程序,也会发生异常,代码会继续并正确地签署PDF
我不确定这是否是iText7
的问题,或者我在创建签名字段时是否犯了错误或忘记了一些重要的事情
有什么办法解决这个问题吗
例外情况
System.NullReferenceException:Der Objektverweis wurde nicht auf eine objektinstancez festgelegt。
在C:\Development\Others\itext7\iText\iText.sign\iText\Signatures\PdfSignatureAppearance.cs:Zeile 584中输入bei iText.Signatures.PdfSignatureAppearance.GetAppearance()。
C:\Development\Others\itext7\iText\iText.sign\iText\Signatures\PdfSigner.cs:Zeile 808中的bei iText.Signatures.PdfSigner.PreClose(IDictionary`2排除大小)。
在C:\Development\Others\itext7\iText\iText.sign\iText\Signatures\PdfSigner.SignExternalContainer(IExternalSignatureContainer-externalSignatureContainer,Int32 estimatedSize)中输入bei iText.Signatures.PdfSigner.SignExternalContainer(IExternalSignatureContainer,Int32 estimatedSize)。
C:\Development\Signature\SignService.Engine\Core\PdfEngine.AddSignature(SignTask任务)中的bei SignService.Engine.Core.PdfEngine.AddSignature(SignTask任务):Zeile 122
我的代码
/// <summary>
/// Add SignatureField to Pdf
/// and digitally sign it
/// </summary>
public SignatureResult AddSignature(SignTask task)
{
_logger.Info("Start Signing PDF");
var prop = task.SignatureProperties;
try
{
var reader = new PdfReader(new MemoryStream(prop.Document));
var stream = new ByteArrayOutputStream();
var signer = new PdfSigner(reader, stream, new StampingProperties().UseAppendMode());
// set appearance
var appearance = signer.GetSignatureAppearance();
appearance.SetReason(prop.SignReason)
.SetLocation(prop.SignLocation)
.SetContact(prop.SignContact);
// set rendering mode
switch (_settings.Pdf.RenderingMode)
{
case SignatureRenderingMode.Description:
appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
break;
case SignatureRenderingMode.Graphic:
appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
break;
case SignatureRenderingMode.GraphicAndDescription:
appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION);
break;
case SignatureRenderingMode.NameAndDescription:
appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION);
break;
}
// set image
if (!string.IsNullOrEmpty(_settings.Pdf.SignatureGraphicPath))
{
if (File.Exists(_settings.Pdf.SignatureGraphicPath))
{
var imageData = ImageDataFactory.Create(_settings.Pdf.SignatureGraphicPath);
appearance.SetSignatureGraphic(imageData);
}
else if (_settings.Pdf.RenderingMode == SignatureRenderingMode.GraphicAndDescription || _settings.Pdf.RenderingMode == SignatureRenderingMode.GraphicAndDescription)
{
throw new Exception("Failed to create Signature Field.\nIf rendering mode is graphic or graphic and description, a signature image must be provided");
}
}
// set visibility
if (prop.Visible)
{
var rect = new Rectangle(prop.X, prop.Y, prop.Width, prop.Height);
appearance.SetPageRect(rect);
appearance.SetPageNumber(1); // todo create setting for this
}
signer.SetFieldName(_settings.Pdf.SignatureFieldName);
// sign field
var signatureContainer = new ExternalSignatureContainer(task, _settings.Ais);
// **Exeption thrown here**
signer.SignExternalContainer(signatureContainer, GetEstimatedSize(task.TimestampOnly));
var tempResult = stream.ToArray();
// set revocation info if active
if (tempResult.Length > 0 && _settings.Ais.AddRevocationInfo)
{
tempResult = AddRevocationInfo(signatureContainer.Crl, signatureContainer.Ocsp, tempResult);
}
reader.Close();
stream.Close();
_logger.Info("Finished signing");
// return sign result
return tempResult.Length > 0
? new SignatureResult
{
Message = "",
Status = RequestStatus.Success,
Document = stream.ToArray(),
Id = prop.Id
}
: new SignatureResult
{
Message = "Failed to sign the Document",
Status = RequestStatus.Failed,
Document = null,
Id = prop.Id
};
}
catch (AisServiceException aisServiceException)
{
_logger.Error($"While requesting Signature an error occured: {aisServiceException.Message}", aisServiceException);
throw;
}
catch (Exception exception)
{
_logger.Error($"While creating signed pdf an error occured: {exception.Message}", exception);
throw new PdfException($"While creating Signed Pdf an error Occured: {exception.Message}");
}
}
任务:
{
"Pdf": {
"Visible": true,
"Position": {
"X": 50,
"Y": 50,
"Height": 100,
"Width": 200
},
"SignatureFieldName": "SignatureField",
"SignatureGraphicPath": "",
"RenderingMode": 1
}
}
"SignatureProperties": {
"Id": "1",
"Document": [DocumentAsByteArray],
"Visible": true,
"SignReason": "Test",
"SignLocation": "Test",
"SignContact": "Test",
"Height": 100,
"Width": 200,
"X": 50,
"Y": 50
}
在代码中,您没有使用
PdfSignatureAppearance.SetCertificate
设置签名者证书。对于像您这样的SignExternalContainer
用例,iText确实不需要证书来执行实际的签名过程,但它确实需要证书来检索有关签名者的信息,以便将其用作名称,并在具有名称和/或描述的可见签名的情况下用于描述(即除纯图形
外的任何渲染模式)
您的设置“RenderingMode”:1
和堆栈跟踪PdfSignatureAppearance.cs:Zeile 584
表明您处于名称和描述
用例中。因此,iText尝试构建描述,访问其签名证书
,并由于该成员为null而失败
要解决此问题,请同时使用PdfSignatureAppearance.SetCertificate
设置签名者证书
如果是描述
和图形和描述
,您也可以使用PDFSignaturePearance.SetLayer2Text
将描述设置为预制值
但是,对于NAME\u和\u DESCRIPTION
,iText无法插入预先计算好的名称
一个更通用的替代方法是自己创建签名外观,只需使用GetLayer2
检索一个PdfFormXObject
,您可以在其上绘制任何可视化效果。在这种情况下,iText不会尝试从证书中检索任何签名者信息。问题发生在PdfSignatureAppeara中nce.GetAppearance()
。这里创建了签名的可视化。因此,最可能的问题是iText需要一些信息来构建外观,并尝试从未设置的属性中检索。您的代码使用\u设置和任务信息填充许多属性。您能否共享t的特定值hem的签名运行失败。@mkl我用设置和任务更新了我的问题,我想如果我不需要“SignExternalContainer”的这些信息…但显然是这样。感谢您的帮助!正如答案中提到的,有很多方法可以满足证书的需要。但是如果您希望iText自动创建一个包含签名者信息的外观,那么只有证书可供使用。mhm另一个问题:此证书是否与签名pdf的证书相匹配之后?没有检查比较它们,在SignExternalContainer
用例中,证书仅用于确定签名者的姓名和/或签名外观描述。因此,您可以使用不同的证书,但它应该以某种方式与实际签名者相关联,以产生合理的外观…P可能是发行人的证书?