用java签名和用cryptoapi签名生成的数据的相互验证
来源:互联网 发布:cfd软件有哪些 编辑:程序博客网 时间:2024/06/05 19:31
cryptoapi的CryptSignHash方法签名生成的数据是pkcs#7格式的,java中通过bouncycastle的CMSSignedData可以实现pkcs#7格式签名数据的验证,利用CMSSignedData签名生成pkcs#7格式数据。代码如下:
注意,如果验证cryptoapi的CryptSignHash方法生成PKCS#1的签名数据,则需要在验证时增加一个null byte,代码如下:
/**
* 验证pkcs7格式的签名数据
* @param signedData pkcs7格式的签名数据
* @return 验证结果
* @throws Exception
*/
public boolean verify(byte[] signedData) 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!");
}else...{
bresult = false;
}
}
return bresult;
}
/**
* 签名生成pkcs7结构数据
* @param signText 原始数据
* @param keystore 密钥库
* @param keyalias 密钥别名
* @param password 密钥库密码
* @return 签名后数据
* @throws Exception
*/
public byte[] sign(byte[] signText,KeyStore keystore,String keyalias,char[] password) throws Exception {
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
Enumeration en = keystore.aliases();
//遍历密钥库的密钥别名
while(en.hasMoreElements()){
String alias = (String)en.nextElement();
logger.debug("keyalias:" + alias);
if(!alias.equalsIgnoreCase(keyalias))continue;
//根据别名从证书中获取私钥
PrivateKey prikey = (PrivateKey) keystore.getKey(keyalias,password);
X509Certificate x509 = null;
//获取该别名对应的证书链
Certificate[] certs = keystore.getCertificateChain(keyalias);
if (certs[0] instanceof X509Certificate) {//user's certificate
x509 = (X509Certificate) certs[0];
}
if (certs[certs.length - 1] instanceof X509Certificate) {//root certificate
x509 = (X509Certificate) certs[certs.length - 1];
}
gen.addSigner(prikey, x509, CMSSignedDataStreamGenerator.DIGEST_SHA1,
"BC");
CertStore certstore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(certs)),"BC");
gen.addCertificatesAndCRLs(certstore);
}
//输出字节流
ByteArrayOutputStream bOut = new ByteArrayOutputStream();//"e:/JavaSignedData.txt"
OutputStream sigOut = gen.open(bOut,true);//false,不含原始数据,减轻传输负担
sigOut.write(signText);//对原始数据进行签名
sigOut.close();
logger.info("pkcs7 signed success!");
byte[] signedData = bOut.toByteArray();//签名后数据
bOut.close();
byte[] signedDataBase64 = Base64.encode(signedData);
logger.debug("签名后数据: " + new String(signedData,CHARSET) + " ");
logger.debug("签名后数据Base64: " + new String(signedDataBase64,CHARSET) + " ");
return signedData;
}
* 验证pkcs7格式的签名数据
* @param signedData pkcs7格式的签名数据
* @return 验证结果
* @throws Exception
*/
public boolean verify(byte[] signedData) 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!");
}else...{
bresult = false;
}
}
return bresult;
}
/**
* 签名生成pkcs7结构数据
* @param signText 原始数据
* @param keystore 密钥库
* @param keyalias 密钥别名
* @param password 密钥库密码
* @return 签名后数据
* @throws Exception
*/
public byte[] sign(byte[] signText,KeyStore keystore,String keyalias,char[] password) throws Exception {
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
Enumeration en = keystore.aliases();
//遍历密钥库的密钥别名
while(en.hasMoreElements()){
String alias = (String)en.nextElement();
logger.debug("keyalias:" + alias);
if(!alias.equalsIgnoreCase(keyalias))continue;
//根据别名从证书中获取私钥
PrivateKey prikey = (PrivateKey) keystore.getKey(keyalias,password);
X509Certificate x509 = null;
//获取该别名对应的证书链
Certificate[] certs = keystore.getCertificateChain(keyalias);
if (certs[0] instanceof X509Certificate) {//user's certificate
x509 = (X509Certificate) certs[0];
}
if (certs[certs.length - 1] instanceof X509Certificate) {//root certificate
x509 = (X509Certificate) certs[certs.length - 1];
}
gen.addSigner(prikey, x509, CMSSignedDataStreamGenerator.DIGEST_SHA1,
"BC");
CertStore certstore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(certs)),"BC");
gen.addCertificatesAndCRLs(certstore);
}
//输出字节流
ByteArrayOutputStream bOut = new ByteArrayOutputStream();//"e:/JavaSignedData.txt"
OutputStream sigOut = gen.open(bOut,true);//false,不含原始数据,减轻传输负担
sigOut.write(signText);//对原始数据进行签名
sigOut.close();
logger.info("pkcs7 signed success!");
byte[] signedData = bOut.toByteArray();//签名后数据
bOut.close();
byte[] signedDataBase64 = Base64.encode(signedData);
logger.debug("签名后数据: " + new String(signedData,CHARSET) + " ");
logger.debug("签名后数据Base64: " + new String(signedDataBase64,CHARSET) + " ");
return signedData;
}
注意,如果验证cryptoapi的CryptSignHash方法生成PKCS#1的签名数据,则需要在验证时增加一个null byte,代码如下:
Signature sig = Signature.getInstance("MD5withRSA","BC");
sig.initVerify(publicKey);
sig.update(data);//data为原始数据
sig.update((byte)0);//增加一个null byte。
sig.verify(signedData)//signedData为cryptoapi签名生成的128位数据。
sig.initVerify(publicKey);
sig.update(data);//data为原始数据
sig.update((byte)0);//增加一个null byte。
sig.verify(signedData)//signedData为cryptoapi签名生成的128位数据。
- 用java签名和用cryptoapi签名生成的数据的相互验证
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java实现xml的签名和验证
- 消息摘要、消息验证码以及用Java的工具生成数学证书签名
- 微信小程序用户数据的签名验证和加解密
- 使用crypto api的签名和验证签名源代码
- openssl在java端的加解密和签名验证
- 的工具生成数字证书,和用程序给数字证书签名、以及用签名后的数学证书签名applet突破applet的访问权限的过程
- PKCS#7的签名和验证
- 生成APK的签名
- 生成的签名文件
- 生成签名的APK
- apk签名和keystore密钥的生成
- C#中Base64之编码,解码方法
- ASP.NET2.0下含有CheckBox的GridView删除选定记录实例
- 解析Java的Class文件格式——解析魔数和版本号
- .NET下正则表达式应用的四个示例
- 用DOM/JDOM解析XML文件
- 用java签名和用cryptoapi签名生成的数据的相互验证
- 著名编程语言Fortran创始人巴库斯
- 打靶算法分析
- 全世界所有程序员都会犯的错误
- 计算Java日期
- Asp.Net细节性问题技巧精萃
- 提高 Java 代码的性能
- 在web下怎样用javascript向listbox中添加或删除所选定的项!
- Smartd