At the moment I wanted to create a digital signature using itext7 and boundy caste on .net razor pages. I found a old tutorial : https://viewbag.wordpress.com/2019/12/24/pdf-digital-signatures-itext7-bouncy-castle-net-core/ and I couldn't make to the end because I got this 2 errors:
Error CS1503 Argument 1: cannot convert from 'Org.BouncyCastle.Crypto.ICipherParameters' to 'iText.Commons.Bouncycastle.Crypto.IPrivateKey' -> pk value
Error CS1503 Argument 2: cannot convert from 'Org.BouncyCastle.X509.X509Certificate[]' to 'iText.Commons.Bouncycastle.Cert.IX509Certificate[]' -> chain value
Code:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using iText.Kernel.Pdf;
using iText.Signatures;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using SSG.Core.Entitites;
using SSG.Infrastructure.Data;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
namespace SSG.Web.Pages.Manufacturers
{
public class IndexModel : PageModel
{
public async Task OnGetAsync()
{
string KEYSTORE = "C:\\Users\\steve\\Desktop\\resources\\cert.pfx";
char[] PASSWORD = "xhbssjsjshjs".ToCharArray();
Pkcs12Store pk12 = new Pkcs12Store(new FileStream(KEYSTORE,
FileMode.Open, FileAccess.Read), PASSWORD);
string alias = null;
foreach (object a in pk12.Aliases)
{
alias = ((string)a);
if (pk12.IsKeyEntry(alias))
{
break;
}
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
string DEST = "C:\\Users\\steve\\Desktop\\resources\\SignedPDF.pdf";
string SRC = "C:\\Users\\steve\\Desktop\\resources\\SampleContract.pdf";
PdfReader reader = new PdfReader(SRC);
PdfSigner signer = new PdfSigner(reader,
new FileStream(DEST, FileMode.Create),
new StampingProperties());
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance.SetReason("My reason to sign...")
.SetLocation("Lahore")
.SetPageRect(new Rectangle(36, 648, 200, 100))
.SetPageNumber(1);
signer.SetFieldName("MyFieldName");
IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256);
signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
}
}
}
Packages installed:
<PackageReference Include="itext7" Version="8.0.1" />
<PackageReference Include="itext7.bouncy-castle-fips-adapter" Version="8.0.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
What I'm doing wrong?
Expected to create a pdf with a digital signature.
There are some breaking changes in the iText signing API between version 7.x and 8.x. The background is that in version 8 both BouncyCastle and BouncyCastle-FIPS are supported. This was done by creating iText wrapper classes for the specific BouncyCastle[-FIPS] classes which have to be used as parameters to the signing methods.
The signing examples in the i7ns-samples repository on github have been updated accordingly. Articles on this topic by third parties may take a bit longer to be updated if at all.
In your case the TestSignBCSimple example class most likely is what you're looking for, with code like this:
string testFileName = @"SOURCE.pdf";
string storePath = @"KEYSTORE.p12";
char[] storePass = "PASSWORD".ToCharArray();
string storeAlias = "ALIAS";
Pkcs12Store pkcs12 = new Pkcs12Store(new FileStream(storePath, FileMode.Open, FileAccess.Read), storePass);
AsymmetricKeyParameter key = pkcs12.GetKey(storeAlias).Key;
X509CertificateEntry[] chainEntries = pkcs12.GetCertificateChain(storeAlias);
IX509Certificate[] chain = new IX509Certificate[chainEntries.Length];
for (int i = 0; i < chainEntries.Length; i++)
chain[i] = new X509CertificateBC(chainEntries[i].Certificate);
PrivateKeySignature signature = new PrivateKeySignature(new PrivateKeyBC(key), "SHA384");
using (PdfReader pdfReader = new PdfReader(testFileName))
using (FileStream result = File.Create("DEST.pdf"))
{
PdfSigner pdfSigner = new PdfSigner(pdfReader, result, new StampingProperties().UseAppendMode());
ITSAClient tsaClient = null;
pdfSigner.SignDetached(signature, chain, null, null, tsaClient, 0, PdfSigner.CryptoStandard.CMS);
}
(TestSignBCSimple test methods TestSignSimple...
)
You can still add an appearance and set a field name like in your example.