我目前已经分配了验证使用openssl生成的数字签名的任务。我收到的文件基本上是两个文件,一个是xml数据,另一个是xml数据的相应签名,用于签名数据的密钥是RSA,算法为SHA1,使用的openssl命令是:openssl smime -sign -binary -in {datafile} -out {signaturefile} -outform der -inkey {privatekey} -signer {publickey} 其中{datafile} =包含要签名的数据的CSV或XML格式的输入文件{signaturefile} =仅包含PKCS#7格式的数字签名的输出文件,与数据文件相同的文件名但扩展名为.sig { privatekey} =用于签名的密钥的私钥部分{publickey} =用于签名的密钥的公钥部分,我编写了一个类来验证这些文件但结果总是返回false意味着验证失败了。下面是我写的代码:有人可以帮助我如何使用java验证openssl分离签名?
public PublicKey pubTest(String path) throws Exception
{
FileInputStream fin = new FileInputStream(path);
CertificateFactory f = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
PublicKey pk = certificate.getPublicKey();
System.out.println(pk);
return pk;
}
public byte[] signature(String sigPath) throws Exception
{
FileInputStream sigfis = new FileInputStream(sigPath);
byte[] sigToVerify = new byte[sigfis.available()];
sigfis.read(sigToVerify);
sigfis.close();
System.out.println(sigToVerify.length);
return sigToVerify ;
}
public boolean verification(PublicKey pubKey , String dataPath , byte[] sigToVerify ) throws Exception, NoSuchProviderException ,SignatureException
{
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(pubKey);
FileInputStream datafis = new FileInputStream(dataPath);
BufferedInputStream bufin = new BufferedInputStream(datafis);
byte[] buffer = new byte[1024];
int len;
while (bufin.available() != 0)
{
len = bufin.read(buffer);
sig.update(buffer, 0, len);
}
System.out.println(buffer.length);
bufin.close();
boolean verifies = sig.verify(sigToVerify);
System.out.println("signature verifies: " + verifies);
return verifies ;
}
答案 0 :(得分:0)
现在很晚,但如果有其他人遇到它:
默认情况下, openssl smime -sign
会生成"间接"分离签名,即不包含encapContentInfo中的数据但使用signedAttrs的签名。见https://www.ietf.org/rfc/rfc3369.txt 5.3至5.6;您需要将数据的哈希与signedAttrs中的message-digest属性进行比较,然后针对signedAttrs验证签名(将IMPLICIT标记恢复为基本)。
标准Java加密不(目前?)执行CMS / PKCS#7但BouncyCastle确实如果这是一个选项。考虑Correct way to sign and verify signature using bouncycastle。