对于PKCS#7的签名和验证本来已经无需再谈,但考虑到默认的PKCS#7签名数据中包含原始数据,这样会带来两个问题:
1,如果原始数据量太大,则会严重影响网络传输速度。
2,如果需要对外部的原始数据进行验证,则难以进行(或者还没发现方法)。
解决第一个问题的方法有两个:
1,在签名时通过参数控制不加入原始数据。
2,对原始数据进行MD5或者SHA1算法后再将该hash值作为原始数据进行签名,因为hash值是固定长度(16或者20byte)。
解决第二个问题的方法也相应有两个:
1,验证时通过传入原始数据进行验证。
2,将原始数据进行一次MD5或者SHA1算法后与PKCS#7中的原始数据进行比较,或者将原始数据进行二次MD5或者SHA1算法后与PKCS#7中的hash值进行比较。
验证部分代码如下:
注意:
在MS的cryptoapi中得到的PKCS#7的原始数据即原始数据的MD5 hash值是17byte的,即多出了一个NULL byte,所以只需要比较前16个即可。
1,如果原始数据量太大,则会严重影响网络传输速度。
2,如果需要对外部的原始数据进行验证,则难以进行(或者还没发现方法)。
解决第一个问题的方法有两个:
1,在签名时通过参数控制不加入原始数据。
2,对原始数据进行MD5或者SHA1算法后再将该hash值作为原始数据进行签名,因为hash值是固定长度(16或者20byte)。
解决第二个问题的方法也相应有两个:
1,验证时通过传入原始数据进行验证。
2,将原始数据进行一次MD5或者SHA1算法后与PKCS#7中的原始数据进行比较,或者将原始数据进行二次MD5或者SHA1算法后与PKCS#7中的hash值进行比较。
验证部分代码如下:
/**
* 验证pkcs7格式的签名数据,从外部传入原始数据
* @param signedData pkcs7格式的签名数据
* @param signData 原始数据
* @return 验证结果
* @throws Exception
*/
public boolean verify( byte [] signedData, byte [] signData) throws Exception {
CMSSignedData sign = new CMSSignedData(signedData);
CertStore certs = sign.getCertificatesAndCRLs("Collection", "BC");
SignerInformationStore signers = sign.getSignerInfos();
Collection c = signers.getSigners();
Iterator it = c.iterator();
boolean bresult = true;
//当有多个签名者信息时需要进行全部验证
while (it.hasNext()) {
SignerInformation signer = (SignerInformation) it.next();
Collection certCollection = certs.getCertificates(signer.getSID());
Iterator certIt = certCollection.iterator();
X509Certificate cert = (X509Certificate) certIt.next();//证书链????
byte[] data = signer.getSignature();
logger.debug("签名后数据:" + data.length);
for (int i = 0; i < data.length; i++) {
System.out.print(" " + data[i]);
}
System.out.println();
logger.debug("签名后数据Base64: " + new String(Base64.encode(data),"utf8"));
if (signer.verify(cert.getPublicKey(), "BC")) {//验证过程???
logger.info(" pkcs7 verifed success!");
//对原始数据计算两次MD5后与签名数据进行比较
MessageDigest md = MessageDigest.getInstance("MD5","BC");
md.update(signData);
// System.out.println("signData=" + new String(signData,"utf8"));
byte[] digestedData1 = md.digest();
// md.update(digestedData1);
// byte[] digestedData2 = md.digest();
//签名原始数据,即原始内容的一次MD5值
byte[] content = (byte[])sign.getSignedContent().getContent();
// System.out.println("content=" + new String(content,"utf8"));
// bresult = CommonUtil.isEqual(digestedData2,signer.getContentDigest());
bresult = CommonUtil.isEqual(digestedData1,content,digestedData1.length);
CommonUtil.displayData(content);
CommonUtil.displayData(digestedData1);
// CommonUtil.displayData(signer.getContentDigest());
}else{
bresult = false;
}
}
return bresult;
}
* 验证pkcs7格式的签名数据,从外部传入原始数据
* @param signedData pkcs7格式的签名数据
* @param signData 原始数据
* @return 验证结果
* @throws Exception
*/
public boolean verify( byte [] signedData, byte [] signData) throws Exception {
CMSSignedData sign = new CMSSignedData(signedData);
CertStore certs = sign.getCertificatesAndCRLs("Collection", "BC");
SignerInformationStore signers = sign.getSignerInfos();
Collection c = signers.getSigners();
Iterator it = c.iterator();
boolean bresult = true;
//当有多个签名者信息时需要进行全部验证
while (it.hasNext()) {
SignerInformation signer = (SignerInformation) it.next();
Collection certCollection = certs.getCertificates(signer.getSID());
Iterator certIt = certCollection.iterator();
X509Certificate cert = (X509Certificate) certIt.next();//证书链????
byte[] data = signer.getSignature();
logger.debug("签名后数据:" + data.length);
for (int i = 0; i < data.length; i++) {
System.out.print(" " + data[i]);
}
System.out.println();
logger.debug("签名后数据Base64: " + new String(Base64.encode(data),"utf8"));
if (signer.verify(cert.getPublicKey(), "BC")) {//验证过程???
logger.info(" pkcs7 verifed success!");
//对原始数据计算两次MD5后与签名数据进行比较
MessageDigest md = MessageDigest.getInstance("MD5","BC");
md.update(signData);
// System.out.println("signData=" + new String(signData,"utf8"));
byte[] digestedData1 = md.digest();
// md.update(digestedData1);
// byte[] digestedData2 = md.digest();
//签名原始数据,即原始内容的一次MD5值
byte[] content = (byte[])sign.getSignedContent().getContent();
// System.out.println("content=" + new String(content,"utf8"));
// bresult = CommonUtil.isEqual(digestedData2,signer.getContentDigest());
bresult = CommonUtil.isEqual(digestedData1,content,digestedData1.length);
CommonUtil.displayData(content);
CommonUtil.displayData(digestedData1);
// CommonUtil.displayData(signer.getContentDigest());
}else{
bresult = false;
}
}
return bresult;
}
在MS的cryptoapi中得到的PKCS#7的原始数据即原始数据的MD5 hash值是17byte的,即多出了一个NULL byte,所以只需要比较前16个即可。