我需要用数字签名对xml文档进行签名,并且需要用该文档生成数字签名xml的.sig文件。我也在使用PKCS7算法。我能够成功地将签名放在xml中。但无法生成.sig文件。我的代码如下:
public static void SignXmlDocumentWithCertificate(XmlDocument doc, X509Certificate2 cert)
{
SignedXml signedxml = new SignedXml(doc);
signedxml.SigningKey = cert.PrivateKey;
Reference reference = new Reference();
reference.Uri = "";
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
signedxml.AddReference(reference);
KeyInfo keyinfo = new KeyInfo();
keyinfo.AddClause(new KeyInfoX509Data(cert));
signedxml.KeyInfo = keyinfo;
signedxml.ComputeSignature();
XmlElement xmlsig = signedxml.GetXml();
doc.DocumentElement.AppendChild(doc.ImportNode(xmlsig, true));
//Console.WriteLine(doc.ImportNode(xmlsig,true));
}
现在我正在生成这样的. sig文件:
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaParameters);
byte[] ciphertext = rsa.Encrypt(keyBytes, false);
string cipherresult = Convert.ToBase64String(ciphertext);
Console.WriteLine(cipherresult);
抛出长度错误的错误\r\n。数字签名后的 xml 是:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<CATALOG>
<PLANT>
<COMMON>Grecian Windflower</COMMON>
<BOTANICAL>Anemone blanda</BOTANICAL>
<ZONE>6</ZONE>
<LIGHT>Mostly Shady</LIGHT>
<PRICE>$9.16</PRICE>
<AVAILABILITY>071099</AVAILABILITY>
</PLANT>
</CATALOG>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>/VUzr4wRNv2e6SzE6TdHLM8c+/A=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>i3gGf2Q......8Q==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIID6D.......fFo=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</xml>
现在我知道我要么做错了,要么错过了什么。我的问题是
正如我的要求是:
尝试以下代码。我将您的代码与msdn中的示例合并。我还在PC上使用了默认用户证书:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
doc.Load(FILENAME);
string computerName = Environment.GetEnvironmentVariable("COMPUTERNAME");
string userName = Environment.GetEnvironmentVariable("USERNAME");
X509Certificate2 cert = GetCertificateFromStore("CN=" + computerName + "\\" + userName);
SignXmlDocumentWithCertificate(doc, cert);
RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
byte[] unencryptedData = Encoding.UTF8.GetBytes(doc.OuterXml);
Stream stream = EncryptFile(unencryptedData,publicKey);
Console.ReadLine();
}
public static void SignXmlDocumentWithCertificate(XmlDocument doc, X509Certificate2 cert)
{
SignedXml signedxml = new SignedXml(doc);
signedxml.SigningKey = cert.PrivateKey;
Reference reference = new Reference();
reference.Uri = "";
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
signedxml.AddReference(reference);
KeyInfo keyinfo = new KeyInfo();
keyinfo.AddClause(new KeyInfoX509Data(cert));
signedxml.KeyInfo = keyinfo;
signedxml.ComputeSignature();
XmlElement xmlsig = signedxml.GetXml();
doc.DocumentElement.AppendChild(doc.ImportNode(xmlsig, true));
//Console.WriteLine(doc.ImportNode(xmlsig,true));
}
private static X509Certificate2 GetCertificateFromStore(string certName)
{
// Get the certificate store for the current user.
X509Store store = new X509Store(StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly);
// Place all certificates in an X509Certificate2Collection object.
X509Certificate2Collection certCollection = store.Certificates;
// If using a certificate with a trusted root you do not need to FindByTimeValid, instead:
// currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, true);
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false);
if (signingCert.Count == 0)
return null;
// Return the first certificate in the collection, has the right name and is current.
return signingCert[0];
}
finally
{
store.Close();
}
}
// Encrypt a file using a public key.
private static MemoryStream EncryptFile(byte[] unencryptedData, RSACryptoServiceProvider rsaPublicKey)
{
MemoryStream stream = null;
using (AesManaged aesManaged = new AesManaged())
{
// Create instance of AesManaged for
// symetric encryption of the data.
aesManaged.KeySize = 256;
aesManaged.BlockSize = 128;
aesManaged.Mode = CipherMode.CBC;
using (ICryptoTransform transform = aesManaged.CreateEncryptor())
{
RSAPKCS1KeyExchangeFormatter keyFormatter = new RSAPKCS1KeyExchangeFormatter(rsaPublicKey);
byte[] keyEncrypted = keyFormatter.CreateKeyExchange(aesManaged.Key, aesManaged.GetType());
// Create byte arrays to contain
// the length values of the key and IV.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = aesManaged.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
stream = new MemoryStream();
try
{
stream.Write(LenK, 0, 4);
stream.Write(LenIV, 0, 4);
stream.Write(keyEncrypted, 0, lKey);
stream.Write(aesManaged.IV, 0, lIV);
// Now write the cipher text using
// a CryptoStream for encrypting.
CryptoStream outStreamEncrypted = new CryptoStream(stream, transform, CryptoStreamMode.Write);
try
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = aesManaged.BlockSize / 8;
do
{
if (offset + blockSizeBytes <= unencryptedData.Length)
{
count = blockSizeBytes;
}
else
{
count = unencryptedData.Length - offset;
}
outStreamEncrypted.Write(unencryptedData, offset, count);
offset += count;
}
while (offset < unencryptedData.Length);
outStreamEncrypted.FlushFinalBlock();
}
catch(Exception ex)
{
Console.WriteLine("Error : {0}", ex.Message);
}
}
catch(Exception ex)
{
Console.WriteLine("Error : {0}", ex.Message);
}
stream.Position = 0;
}
}
return stream;
}
}
}
我希望我们拥有iPhone的员工能够让公众对一份文件进行数字签名,该文件最初是基于Spring的网络表单。 此表格仅在我们的内部网上,仅由我们的员工填写。 到目前为止,我的研究考虑了一些可能的解决方案: 手机屏幕上的电子湿墨水签名 目的是证明某个人签署了一份文件。 1从技术上讲是可能的,但并不重要,因为它很容易被复制。 是否可以在iOS设备上通过浏览器和javascript捕获指纹? 3能适应这种
我一直在网络和java教程中寻找这一点。但我没有澄清如何为文档生成数字签名。java教程对此进行了解释,但我真正想要的是 用户附带一个文件和一个字符串密钥 使用该密钥,文件被数字签名 相应的公钥,该标志与该文档一起发布 那么,如何转换给定的String私钥来做到这一点。在尝试java教程和web中给出的示例(带有将字节从字符串而不是文件中放置的一些变体)时,我遇到了如下异常
我需要一些使用OpenSSL的帮助,以便使用C(Windows和Linux)生成数据块的签名。该应用程序与谷歌认证有关。谷歌文档中的说明如下: “使用从Google开发者控制台获得的私钥,使用SHA256withRSA(也称为RSASSA-PKCS1-V1_5-Sign,使用SHA-256哈希函数)对输入的UTF-8表示形式进行签名。输出将是字节数组。” 私钥是一个密码。p12包含1660字节二进
signature1值总是39字节[]数组,当我转换为十六进制时,长度大于64。我想在C#中从P-128 ECC算法生成精确的64长度十六进制签名值。 让我解释下面的代码: > 对必须签名的纯文本消息进行哈希
当我从REST客户端调用APIendpoint时,由于涉及Signature而出错。 请求: 主持人:https://xxx.execute-api.ap-southeast-1.amazonaws.com/latest/api/name 授权: AWS4-HMAC-SHA256凭据=/20160314/ap-东南-1/执行-api/aws4_request, SignedHeaders=host
我正在尝试向现有的数字签名pdf(认证签名)中添加一个空签名字段。 我有一个工作流,其中许多用户将签署该文档(批准签名),该文档创建时带有“n”个空签名字段,每个用户一个,我们的应用程序首先应用一个不可见的认证签名,然后每个用户可以在各自的字段中签署该文档,但由于工作流中意外的更改,其他用户可能希望签名,因此,我们希望添加相应的空签名字段,然后应用签名。 我试图将空字段(带有单元格事件的表)添加到