InvalidKeyException using MSCAPI and IAIK

1.1k Views Asked by At

I use Sun's MSCAPI provider in my application to retrieve a signing certificate. The signer's privatekey is a sun.security.mscapi.RSAPrivateKey. IAIK does not seem to recognize this class (See error below). I do not understand why. What are the solutions to my problem?

Thanks in advance !

java.security.NoSuchAlgorithmException: Error computing signature value: iaik.cms.CMSException: Unable to calculate signature: java.security.InvalidKeyException: Class does not represent an RSA key: sun.security.mscapi.RSAPrivateKey
     at iaik.cms.SignedData.addSignerInfo(Unknown Source)
     at testIaikCmsWithMsCAPIProvider.init(testIaikCmsWithMsCAPIProvider.java:69)
     at testIaikCmsWithMsCAPIProvider.main(testIaikCmsWithMsCAPIProvider.java:39)

EDIT :

This is my "dirty" classTest :

import iaik.asn1.structures.AlgorithmID;
import iaik.cms.CMSException;
import iaik.cms.CMSParsingException;
import iaik.cms.ContentInfo;
import iaik.cms.IssuerAndSerialNumber;
import iaik.cms.SignedData;
import iaik.cms.SignerInfo;
import iaik.utils.Util;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class testIaikCmsWithMsCAPIProvider {

    public static final String SunMscapiClassName = "sun.security.mscapi.SunMSCAPI";
    private Provider           provider;
    private String             providerName;
    private String             alias              = "Sample Alias";
    private X509Certificate    signerCertificate;
    private PrivateKey         privateKey;

    public static void main(String[] args) {
        testIaikCmsWithMsCAPIProvider test = new testIaikCmsWithMsCAPIProvider();
        test.init();
    }

    private void init() {
        try {
            Class<Provider> sunmscapiClass = (Class<Provider>)Class.forName(SunMscapiClassName);
            Provider sunmscapiInstance = sunmscapiClass.newInstance();
            Security.addProvider(sunmscapiInstance);

            KeyStore ks = null;

            ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
            ks.load(null, null);

            this.provider = ks.getProvider();
            this.providerName = ks.getProvider().getName();

            this.initMscapiProgrammaticMode(ks);

            X509Certificate[] certificateChain = new X509Certificate[1];
            certificateChain[0] = signerCertificate;
            iaik.x509.X509Certificate[] iaikCertificateChain = Util.convertCertificateChain(certificateChain);
            IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(iaikCertificateChain[0]);
            AlgorithmID signatureAlg = AlgorithmID.rsaEncryption;
            AlgorithmID digestAlg = AlgorithmID.sha1;
            SignerInfo signerInfo = new SignerInfo(issuerSerial, digestAlg, signatureAlg, privateKey);
            Path path = Paths.get("file.pdf");
            byte[] signatureFileContent = Files.readAllBytes(path);
            SignedData signedData = new SignedData(signatureFileContent, SignedData.EXPLICIT);
            signedData.setCertificates(iaikCertificateChain);
            signedData.addSignerInfo(signerInfo);

            byte[] digitalSignature = new ContentInfo(signedData.getContentType()).getEncoded();
            FileOutputStream fos = new FileOutputStream("signature.pdf");
            fos.write(digitalSignature);
            fos.close();

            System.out.println(providerName + provider + alias + signerCertificate + privateKey.getClass());
        }
        catch(Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void initMscapiProgrammaticMode(KeyStore ks) throws KeyStoreException, UnrecoverableKeyException,
            NoSuchAlgorithmException {

        X509Certificate javaCert = (X509Certificate)ks.getCertificate(this.alias);
        this.signerCertificate = javaCert;

        // retrieve associated private key
        this.privateKey = (PrivateKey)ks.getKey(this.alias, null);

    }

}
1

There are 1 best solutions below

0
On BEST ANSWER

After months of research, I finally found the solution. It is with great pleasure, guys, I will share it now:

To be very simple, when trying to sign IAIK uses it's own provider by default. Now we want to use the one of MSCAPI. That's why we need him specify this line so it can find the right provider:

signedData.setSecurityProvider (new SecurityProvider ());