Спустя более двух недель, я заметил, в чем проблема, хотя я не нашел полного решения.
Сначала я извлек проблему из файла PKCS7 и воспроизвел исключение со следующим исходным кодом:
import diz.firma.keyStore.SmartCard;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
public class TestFirma3 {
public static void main(String args[]) throws Exception {
//Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
SmartCard sm = new SmartCard();
KeyStore ks = sm.loadKeyStore("1234");
//KeyPair keyPair = generateKeyPair(999);
byte[] data = "original".getBytes("UTF-8");
//byte[] data = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 };
//byte[] digitalSignature = signData(data, keyPair.getPrivate());
byte[] digitalSignature = signData(data,
(PrivateKey)ks.getKey(sm.getAlias(), null),ks.getProvider());
boolean verified;
//verified = verifySig(data, keyPair.getPublic(), digitalSignature);
verified = verifySig(data, ks.getCertificate(sm.getAlias()).
getPublicKey(),ks.getProvider(), digitalSignature);
System.out.println("verified:" + verified) ;
//keyPair = generateKeyPair(888);
//verified = verifySig(data, keyPair.getPublic(), digitalSignature);
//System.out.println(verified);
}
public static byte[] signData(byte[] data, PrivateKey key,Provider p) throws Exception {
Signature signer = Signature.getInstance("SHA1withRSA",p);
//Signature signer = Signature.getInstance("SHA1withRSA",Security.getProviders()[10]);
signer.initSign(key);
signer.update(data);
return (signer.sign());
}
public static boolean verifySig(byte[] data, PublicKey key, Provider p, byte[] sig) throws Exception {
Signature signer = Signature.getInstance("SHA1withRSA",p);
//Signature signer = Signature.getInstance("SHA1withRSA");
signer.initVerify(key);
signer.update(data);
boolean valido = false;
try{
valido = signer.verify(sig);
}catch(Exception e){
e.printStackTrace();
valido = false;
}
return valido;
}
public static KeyPair generateKeyPair(long seed) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("DSA");
SecureRandom rng = SecureRandom.getInstance("SHA1PRNG", "SUN");
rng.setSeed(seed);
keyGenerator.initialize(1024, rng);
return (keyGenerator.generateKeyPair());
}
}
В этом коде (извлеченном из примера в сети) я изменил ключ генератора и взял его со своей карты. Я снова получил исключение, не используя файлы PKCS7.
Рассматривая всех провайдеров (с помощью Security.getProviders () вы можете получить их всех; они определены в файле java.security, но его можно добавлять или извлекать во время выполнения), и я использовал всех для подписи и проверить, я узнал, что:
- Если ни один поставщик не выбран при создании экземпляра Signature, он по умолчанию использует SunRsaSign.
- Моя подпись подтверждена 2 провайдерами:
a) С поставщиком SunMSCAPI, который использует Microsoft Crypt API.
б) с провайдером, созданным устройством чтения смарт-карт, в моем случае Siemens.
- Считывание другой смарт-карты, не принадлежащей Siemens, проверяется с помощью SunRsaSign и SunJSSE.
В данный момент я выясняю проблему и работаю, используя SunMSCAPI для проверки, но мне нужно выполнить проверку на машине IBM. Программное обеспечение Siemens предоставляет возможность установки в Unix, но я не могу заставить его работать. И, используя SunMSCAPI, я полагаю, он недоступен для IBM.
Итак, мне нужно найти поставщика, который правильно проверяет в IMB подпись, которую SunRsaSign возвращает SignatureException.