C# 使用.Net中的p12/pfx文件对数据进行签名-发生内部证书链接错误
我正在尝试将一些java代码移植到C#,但在签署数据时遇到了一个问题。我收到的错误是“发生了内部证书链接错误。” 代码在我的机器上成功地用java运行,但在C#中没有 下面是我的C代码,它在ComputeSignature时抛出异常:C# 使用.Net中的p12/pfx文件对数据进行签名-发生内部证书链接错误,c#,encryption,cryptography,x509,x509certificate2,C#,Encryption,Cryptography,X509,X509certificate2,我正在尝试将一些java代码移植到C#,但在签署数据时遇到了一个问题。我收到的错误是“发生了内部证书链接错误。” 代码在我的机器上成功地用java运行,但在C#中没有 下面是我的C代码,它在ComputeSignature时抛出异常: //Import the certificate var certificate2Collection = new X509Certificate2Collection(); certificate2Collection.Impo
//Import the certificate
var certificate2Collection = new X509Certificate2Collection();
certificate2Collection.Import(certificateFilePath, "**password**", X509KeyStorageFlags.DefaultKeySet);
//Only one cert in pks file
var cert2 = certificate2Collection[0];
//create data to be signed
var time = DateTime.Now.ToString("dd/MM/yyyy") + " 00:00:00";
var modifiedTimestamp = userName + "|" + time;
var dataToSign = Encoding.ASCII.GetBytes(modifiedTimestamp);
var content = new ContentInfo(dataToSign);
var signedMessage = new SignedCms(content);
var cmsSigner = new CmsSigner(cert2);
signedMessage.**ComputeSignature**(cmsSigner);
byte[] signedBytes = signedMessage.Encode();
string signedData = Convert.ToBase64String(signedBytes);
以下是有效的java代码:
final String time = new java.text.SimpleDateFormat("dd/MM/yyyy").format(new java.util.Date());
final String timestamp = time + " 00:00:00";
// Create the data to be signed
final String modifiedTimestamp = userName + "|" + timestamp;
final byte[] ba = modifiedTimestamp.getBytes();
final byte[] signedData;
final KeyStore ks = KeyStore.getInstance(certificateStoreType);
ks.load(certificateStream, certificatePassword);
// Get the certificate from the keystore using the alias
final X509Certificate inCert = (X509Certificate) ks.getCertificate(certificateAlias == null ? userName : certificateAlias);
// Get the private key using the alias and the password
final PrivateKey privateKey = (PrivateKey) ks.getKey(keyAlias == null ? userName : keyAlias, certificatePassword);
// Get the algorithm name from the certificate
final String issuerSigAlg = inCert.getSigAlgName();
// Get the signature for the specified algorithm
final Signature sig = Signature.getInstance(issuerSigAlg);
// Sign the message
sig.initSign(privateKey);
sig.update(ba);
signedData = sig.sign();
提前感谢您提供的任何帮助
编辑
我现在已经可以工作了,但是我的代码已经有了很大的改变。我已经自动转换了java代码,以查看生成了什么。结果如下,但这确实对所使用的加密算法做出了某些假设:-
var buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int) fs.Length);
var certificate2 = new X509Certificate2(buffer, certificatePassword);
string timestamp = DateTime.Now.ToShortDateString() + " 00:00:00";
string modifiedTs = userName + "|" + timestamp;
var cryptoKey = new RSACryptoServiceProvider();
var formatter = new RSAPKCS1SignatureFormatter(cryptoKey);
formatter.SetKey(certificate2.PrivateKey);
formatter.SetHashAlgorithm("SHA1");
var bytes = Encoding.UTF8.GetBytes(modifiedTs);
var rgbBytes = new SHA1CryptoServiceProvider().ComputeHash(bytes);
string signature = Convert.ToBase64String(formatter.CreateSignature(rgbBytes));
看起来第一个证书(您在C#中访问的)不是您期望的证书-不是具有私钥的最终实体证书,而是中间或根CA。因此,签名者类无法使用它进行签名。检查假设是否正确的最简单方法是尝试集合中的所有证书,并查看其中是否有任何证书有效 嗨,尤金,谢谢你的帮助。实际上,文件中只有一个证书。还有其他想法吗?这不是编辑,这是答案。把它贴在下面并接受它(一段时间后)。