0

My project consists in signing a PDF file using PKS11 (usb smartcard).

What I need is:

1) Plug in the USB smart card (and let the OS load the certificate in CurrentUser store (Windows))

2) Call an application , no GUI needed, that sign a determined PDF with the loaded cert.

Step 2 would need the user to input the PIN of the smartcard. For now that is not a concern, I can statically set it for testing purposes.

The posts I have been reading are:

checking-for-the-accessibility-of-smart-card-private-keys-in-windows-10

find-certificate-on-smartcard-currently-on-reader

load-a-smart-card-or-other-private-certificate-in-cryptoserviceprovider-for-sign

how-do-i-sign-a-pdf-document-using-a-certificate-from-the-windows-cert-store

sign-pdf-with-itextsharp-5-3-3-and-usb-token

// Set up the PDF IO
PdfReader reader = new PdfReader(@"C:\Users\martin\Documents\tosign.pdf");
PdfStamper stamper = PdfStamper.CreateSignature(reader,
new FileStream(@"C:\Users\martin\Documents\SignedPdf.pdf", FileMode.Create), 
'\0');
PdfSignatureAppearance sap = stamper.SignatureAppearance;
sap.Reason = "For no apparent reason";
sap.Location = "Place";

var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2 cert = fcollection[0];



BcX509.X509CertificateParser cp = new BcX509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
    cp.ReadCertificate(cert.RawData)
};
Console.WriteLine(cert);

X509Certificate2 signatureCert = new X509Certificate2(cert);
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1");

MakeSignature.SignDetached(sap, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);

I get a runtime error

System.ArgumentException: 'Unknown encryption algorithm System.Security.Cryptography.RSACng'

in the line

IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1");

I read somewhere that externalSignature is to be implemented with custom code depending on the USB vendor. Though in all the posts mentioned here, it seems that line should work with no problems. I tried to change the algorithm to SHA-256. Also I have been digging Github code of IExternalSignature interface to try to get a grasp out of it.

In theory, I know the private key of the USB device will never be accessible, therefore I can not just try to sign with a "getprivatekey" method kind.

In practice, I am a MEAN stack and Python dev, I have never coded in C#.

halfer
  • 19,824
  • 17
  • 99
  • 186
uajov6
  • 413
  • 7
  • 13
  • As far as I can see in the `X509Certificate2Signature` source, it only supports the `DSACryptoServiceProvider` and `RSACryptoServiceProvider` but not the newer `DSACng`, `ECDsaCng`, and `RSACng` classes. I think you'll have to extend the `X509Certificate2Signature` class to support at least also `RSACng`. – mkl Mar 28 '18 at 13:22
  • In order to avoid extending classes, would it work out to go back to older versions? – uajov6 Mar 28 '18 at 15:18
  • I don't know whether basing one's work on an older .Net version will help. – mkl Mar 28 '18 at 17:02
  • Did you got any results? I'm facing the same error, BUT, it started when I turned to .NetCore. Because in .Net works. – Angelo Bernardi Feb 25 '21 at 20:05

0 Answers0