我对PKCS7证券文件有一个很大的奇怪问题。 我创建了一个像http://www.thatsjava.com/java-tech/85019/中建议的p7s文件,它创建文件并仅使用sun库验证它。它工作正常 当我想验证此文件时,问题就开始了。它返回此异常:
java.security.SignatureException: Signature encoding error
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:185)
at java.security.Signature$Delegate.engineVerify(Signature.java:1140)
at java.security.Signature.verify(Signature.java:592)
at sun.security.pkcs.SignerInfo.verify(SignerInfo.java:374)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:494)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:511)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:533)
at firma.FirmaDigitalImpl.firmarCadenaSun(FirmaDigitalImpl.java:553)
at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:249)
at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:147)
at firma.TestFirma.main(TestFirma.java:75)
Caused by: java.io.IOException: Sequence tag error
at sun.security.util.DerInputStream.getSequence(DerInputStream.java:280)
at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:209)
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:174)
... 10 more
但问题并不总是出现,只是只有一种用于签名的证书。我会更好地解释。 我有两个证书(存储到智能卡中),第一个工作正常;我创建了p7s,然后我正确验证,但第二个证书允许我创建p7s文件但是当我验证它时,它返回SignatureException。我认为p7s文件是错误的,但我测试了其他人的应用程序,它看起来是正确的。此外,这个文件被发送抛出webservice,它返回它是好的!
有关更多信息,如果使用不同的工具(.net和capicom)创建p7s文件并使用相同的证书,那么我可以正确验证。
我已经找到了解决方案,但没有。我在类似情况下发现了相同的异常,但是建议的解决方案对我不起作用,或者没有出现。
非常感谢任何寻找解决方案的建议。
答案 0 :(得分:1)
可能是编码问题:文本与二进制。 PKCS7可以是DER编码的二进制格式或PEM格式(base64编码的DER)。在文本编辑器(例如记事本)中打开文件,看看有效的文件是二进制还是文本。
答案 1 :(得分:1)
经过两周多的时间,我注意到了问题所在,虽然我找不到完整的解决方案。
首先,我从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文件中定义,但可以在运行时添加或从中获取),并且我使用每个人来签名和验证,我发现:
此时,我发现问题和使用SunMSCAPI进行验证的工作日,但我必须验证IBM机器。西门子软件提供了一个安装到Unix的选项,但我无法让它工作。使用SunMSCAPI,我认为它不适用于IBM。
因此,我必须找到一个在IMB中正确验证SunRsaSign返回SignatureException的签名的提供程序。