InvalidKeyException с использованием MSCAPI и IAIK
Я использую провайдера 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)
РЕДАКТИРОВАТЬ:
Это мой "грязный" класс Test:
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 ответ
Решение
После месяцев исследований я наконец нашел решение. Ребята, с большим удовольствием поделюсь этим сейчас
Чтобы быть очень простым, при попытке подписать IAIK использует свой собственный поставщик по умолчанию. Теперь мы хотим использовать один из MSCAPI. Вот почему нам нужно, чтобы он указал эту строку, чтобы он мог найти подходящего поставщика:
signedData.setSecurityProvider (new SecurityProvider ());