2

アプリケーションで Sun の MSCAPI プロバイダを使用して署名証明書を取得しています。署名者の秘密鍵は、sun.security.mscapi.RSAPrivateKey です。IAIK はこのクラスを認識していないようです (以下のエラーを参照)。私はなぜなのか理解していない。私の問題の解決策は何ですか?

前もって感謝します !

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)

編集 :

これは私の「汚い」 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);

    }

}
4

1 に答える 1

2

何ヶ月もの調査の後、私はついに解決策を見つけました。皆さん、とてもうれしく思います。今それを共有します:

非常に簡単に言うと、IAIK に署名しようとすると、デフォルトで独自のプロバイダーが使用されます。次に、MSCAPI のものを使用します。そのため、適切なプロバイダーを見つけることができるように、次の行を指定する必要があります。

signedData.setSecurityProvider (new SecurityProvider ());
于 2014-10-20T09:17:02.080 に答える