Pkcs11Interop / Pkcs11Interop.X509Store

Easy to use PKCS#11 based X.509 certificate store
Apache License 2.0
32 stars 18 forks source link

Added ICspAsymmetricAlgorithm implementation #4

Closed vazmuten closed 5 months ago

vazmuten commented 5 years ago

Updated Pkcs11RsaProvider to support ICspAsymmetricAlgorithm in order to be possible the Private key to be imported into X509Certificate2 object. Useful when X509Certificate2 is passed into a code and somewhere later the signing is done.

Added properties:

private byte[] _cspBlob;

Updated methods:

// added _cspBlob data generation from RSACryptoServiceProvider using the PublicKey
internal Pkcs11RsaProvider(Pkcs11X509CertificateContext certContext);

Added methods:

public CspKeyContainerInfo CspKeyContainerInfo; //NOTE not precise and could be improved
public byte[] ExportCspBlob(bool includePrivateParameters);
public void ImportCspBlob(byte[] _cspBlob);

Possible usage:

// Load the Pkcs11X509Store 
Pkcs11X509Store store = new Pkcs11X509Store(@"C:\Windows\SysWow64\cmP11.dll", new ConstPinProvider("1234"));

Pkcs11X509Certificate pkcs11cert = store.Slots[0].Token.Certificates[0];

// Crate X509Certificate2 object with just a certificate
X509Certificate2 x509Certificate2 = new X509Certificate2(pkcs11cert.Info.RawData);

// Get PKCS#11 based private key
RSA rsaPrivateKey = (RSA)pkcs11cert.GetRSAPrivateKey();

//Set the private key to be used by Pkcs11RsaProvider
Pkcs11RsaProvider pkcs11RsaPrivateKey = (Pkcs11RsaProvider)rsaPrivateKey;

// Extend X509Certificate2 with the private key
x509Certificate2.PrivateKey = pkcs11RsaPrivateKey;

// Do the signature          
byte[] sig = x509Certificate2.GetRSAPrivateKey().SignData(input, hashAlgorithmName, rSASignaturePadding);
jariq commented 5 years ago

Do I understand it correctly that the only motivation for this is change is to "carry" an instance of Pkcs11RsaProvider class in the instance of X509Certificate2 class?

vazmuten commented 5 years ago

Exactly because X509Certificate2 class is mostly used for signing. After this change we managed to sign using FirmaXadesNet (with a minor fix) which is the only option we found that produces valid XADES-XL signatures. We also use other code that requires X509Certificate2 objects in order later to do the signature. If you wish rewrite it in a better/proper way but this update made things work for us.

jariq commented 5 years ago

After this change we managed to sign using FirmaXadesNet (with a minor fix)

Is it possible to see that minor fix somewhere?

vazmuten commented 5 years ago

Sure! Just did also a pull request to FirmaXadesNet project: https://github.com/ctt-gob-es/FirmaXadesNet45/pull/15

Just added a try/catch to cover the case when certificate.PrivateKey is not of RSACryptoServiceProvider type. After this we successfully signed the XML.

jariq commented 5 months ago

I understand that this code helped you to resolve your problem. However I cannot merge it because it is just faking windows integration. It returns the name of non-existing CSP. Any app that will try to communicate with such CSP will fail. You've already seen that with FirmaXadesNet and that's the reason why you had to modify its code. Better way to modify FirmaXadesNet code would be to pass AsymmetricAlgorithm along with X509Certificate2. Take a look at CmsSigner Constructors for a real-world example from .NET team. Sample usage then can be seen in our BasicSignedCmsTest.