“的结果”;“Java实用程序”;与“不匹配”;C“效用”;签名数据时
嗯,我陷入了使用Java实用程序对数据进行签名的过程中 我需要创建一个Java程序,该程序将根据作为输入数据提供的base64编码字符串对数据进行签名 在这里,我可以使用提供的特定证书生成签名数据,但问题是:签名数据时,“Java实用程序”的结果与“C#实用程序”不匹配 这是我的C#程序:“的结果”;“Java实用程序”;与“不匹配”;C“效用”;签名数据时,java,c#,digital-signature,Java,C#,Digital Signature,嗯,我陷入了使用Java实用程序对数据进行签名的过程中 我需要创建一个Java程序,该程序将根据作为输入数据提供的base64编码字符串对数据进行签名 在这里,我可以使用提供的特定证书生成签名数据,但问题是:签名数据时,“Java实用程序”的结果与“C#实用程序”不匹配 这是我的C#程序: //Get certificate based on given thumbprint X509Certificate2 certificate = GetCertificate(certThumbPrint
//Get certificate based on given thumbprint
X509Certificate2 certificate = GetCertificate(certThumbPrint);
ContentInfo contentInfo = new ContentInfo(Convert.FromBase64String(data));
SignedCms signedCms = new SignedCms(contentInfo, false);
CmsSigner cmsSigner = new CmsSigner(certificate);
signedCms.ComputeSignature(cmsSigner, false);
return Convert.ToBase64String(signedCms.Encode());
package com.test;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
public class TestSignData {
public static void main(String[] args) throws Exception {
//First load the keystore object by providing the p12 file path
KeyStore clientStore = KeyStore.getInstance("Windows-MY");
//replace testPass with the p12 password/pin
clientStore.load(null, null);
Enumeration<String> aliases = clientStore.aliases();
String aliaz = "";
System.out.println(aliases.hasMoreElements());
while(aliases.hasMoreElements()){
aliaz = aliases.nextElement();
System.out.println("aliaz::"+aliaz);
if(clientStore.isKeyEntry(aliaz)){
break;
}
}
X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz);
//Data to sign
byte[] dataToSign = "QXNob2s=".getBytes();
int nread = dataToSign.length;
//compute signature:
Signature signature = Signature.getInstance("Sha1WithRSA");
signature.initSign((PrivateKey)clientStore.getKey(aliaz, null));
signature.update(dataToSign, 0, nread);
byte[] signedData = signature.sign();
//load X500Name
X500Name xName = new X500Name(c.getSubjectX500Principal().getName());
System.out.println("xName:::"+xName);
//load serial number
BigInteger serial = c.getSerialNumber();
//laod digest algorithm
AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.SHA_oid);
//load signing algorithm
AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);
//Create SignerInfo:
SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData);
//Create ContentInfo:
ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
//Create PKCS7 Signed data
PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
new java.security.cert.X509Certificate[] { c },
new SignerInfo[] { sInfo });
//Write PKCS7 to bYteArray
DerOutputStream dOut = new DerOutputStream();
p7.encodeSignedData(dOut);
byte[] encodedPKCS7 = dOut.toByteArray();
String base64SignatureData = org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
System.out.println(base64SignatureData);
}
}
其中,data
将是base64编码字符串,certThumbPrint
将是特定证书的唯一值
这是我的Java程序:
//Get certificate based on given thumbprint
X509Certificate2 certificate = GetCertificate(certThumbPrint);
ContentInfo contentInfo = new ContentInfo(Convert.FromBase64String(data));
SignedCms signedCms = new SignedCms(contentInfo, false);
CmsSigner cmsSigner = new CmsSigner(certificate);
signedCms.ComputeSignature(cmsSigner, false);
return Convert.ToBase64String(signedCms.Encode());
package com.test;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
public class TestSignData {
public static void main(String[] args) throws Exception {
//First load the keystore object by providing the p12 file path
KeyStore clientStore = KeyStore.getInstance("Windows-MY");
//replace testPass with the p12 password/pin
clientStore.load(null, null);
Enumeration<String> aliases = clientStore.aliases();
String aliaz = "";
System.out.println(aliases.hasMoreElements());
while(aliases.hasMoreElements()){
aliaz = aliases.nextElement();
System.out.println("aliaz::"+aliaz);
if(clientStore.isKeyEntry(aliaz)){
break;
}
}
X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz);
//Data to sign
byte[] dataToSign = "QXNob2s=".getBytes();
int nread = dataToSign.length;
//compute signature:
Signature signature = Signature.getInstance("Sha1WithRSA");
signature.initSign((PrivateKey)clientStore.getKey(aliaz, null));
signature.update(dataToSign, 0, nread);
byte[] signedData = signature.sign();
//load X500Name
X500Name xName = new X500Name(c.getSubjectX500Principal().getName());
System.out.println("xName:::"+xName);
//load serial number
BigInteger serial = c.getSerialNumber();
//laod digest algorithm
AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.SHA_oid);
//load signing algorithm
AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);
//Create SignerInfo:
SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData);
//Create ContentInfo:
ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
//Create PKCS7 Signed data
PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
new java.security.cert.X509Certificate[] { c },
new SignerInfo[] { sInfo });
//Write PKCS7 to bYteArray
DerOutputStream dOut = new DerOutputStream();
p7.encodeSignedData(dOut);
byte[] encodedPKCS7 = dOut.toByteArray();
String base64SignatureData = org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
System.out.println(base64SignatureData);
}
}
package.com.test;
导入java.math.biginger;
导入java.security.KeyStore;
导入java.security.PrivateKey;
导入java.security.Signature;
导入java.security.cert.x509证书;
导入java.util.Enumeration;
导入sun.security.pkcs.ContentInfo;
导入sun.security.pkcs.PKCS7;
导入sun.security.pkcs.SignerInfo;
导入sun.security.util.DerOutputStream
导入sun.security.util.DerValue;
导入sun.security.x509.AlgorithmId;
导入sun.security.x509.X500Name;
公共类TestSignData{
公共静态void main(字符串[]args)引发异常{
//首先通过提供p12文件路径加载密钥库对象
KeyStore clientStore=KeyStore.getInstance(“Windows MY”);
//用p12密码/pin替换testPass
load(null,null);
枚举别名=clientStore.aliases();
字符串aliaz=“”;
System.out.println(别名.hasMoreElements());
while(别名.hasMoreElements()){
aliaz=别名.nextElement();
System.out.println(“aliaz::”+aliaz);
if(clientStore.isKeyEntry(aliaz)){
打破
}
}
X509Certificate c=(X509Certificate)clientStore.getCertificate(aliaz);
//要签名的数据
byte[]dataToSign=“QXNob2s=“.getBytes();
int nread=数据到符号长度;
//计算签名:
Signature-Signature=Signature.getInstance(“Sha1WithRSA”);
signature.initSign((PrivateKey)clientStore.getKey(aliaz,null));
签名。更新(dataToSign,0,nread);
字节[]signedData=signature.sign();
//加载X500Name
X500Name xName=新的X500Name(c.getSubjectX500Principal().getName());
System.out.println(“xName::”+xName);
//装载序列号
BigInteger serial=c.getSerialNumber();
//laod摘要算法
AlgorithmId digestAlgorithmId=新的AlgorithmId(AlgorithmId.SHA_oid);
//负载签名算法
AlgorithmId signAlgorithmId=新的AlgorithmId(AlgorithmId.rsaid);
//创建签名信息:
SignerInfo sInfo=新的SignerInfo(xName、serial、digestAlgorithmId、signAlgorithmId、signedData);
//创建内容信息:
ContentInfo cInfo=newcontentinfo(ContentInfo.DIGESTED_DATA_OID,new DerValue(DerValue.tag_OctetString,dataToSign));
//创建PKCS7签名数据
PKCS7 p7=新的PKCS7(新算法ID[]{digestAlgorithmId},cInfo,
新的java.security.cert.X509Certificate[]{c},
新签署人[]{sInfo});
//将PKCS7写入bYteArray
DerOutputStream dOut=新的DerOutputStream();
p7.编码签名数据(dOut);
字节[]encodedPKCS7=dOut.toByteArray();
String base64SignatureData=org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
System.out.println(base64SignatureData);
}
}
有谁能指导我得到基于“C#”的实用程序返回的确切结果吗
注意:在本地检查此程序时,您可以将任何证书作为输入,但两个程序的结果应该相同,这是我的主要要求
如果有人能就此给我快速回复,我将不胜感激
谢谢大家! 首先,正如Artjom所评论的那样,数字签名并不总是确定的,同一数据中具有相同密钥的两个(或多个)签名很可能不同,并且都(或全部)有效。您不会通过将签名与新生成的、甚至是预先存在的签名进行比较来验证签名 你正在做一些肯定或可能错误的事情,需要纠正,以及其他可能不同但不一定错误的事情 明确:您的dotNET代码使用的是从base64解码后的数据,您的Java代码使用的是编码值(用于散列和发送) 半确定:在创建SignerInfo时使用证书主题和序列号,它应该是issuer和序列号。如果您的证书是自签名的,则颁发者和主题是相同的,这并不重要 明确:您正在使用(的OID)摘要数据作为数据的contentType,它应该是数据。(摘要数据是包含数据和摘要的摘要数据结构消息的类型,即) 很有可能:MSDN并没有说我可以找到(而且我也无法轻松测试)hash dotNET用于RSA签名的内容,但SHA1不再被认为是最佳实践,所以它可能会使用更好的方法。如果是这样的话,这是一个差异,即使实践不佳,也不一定是错误的 可能:类似地,我不知道dotNET是否使用SignedAttributes,但我认为这是可能的,因为这是一种良好的做法。你的Java代码绝对不会。如果是这样的话,这是一个区别,但并不是真的错 很可能:类似地,我不知道dotNET是否自动包含/添加链证书,这是明确推荐的良好做法。您的Java代码没有。如果您的证书是自签名的,则没有链证书,这无关紧要 PS:Java8正式拥有
java.util.Base64
并返回到6(在l